@guiexpert/react-table 18.1.78 → 18.1.80

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.
Files changed (3) hide show
  1. package/index.cjs +10 -7
  2. package/index.js +1206 -206
  3. package/package.json +5 -3
package/index.js CHANGED
@@ -9,14 +9,14 @@ function le(p, e = 500) {
9
9
  }, e);
10
10
  };
11
11
  }
12
- class k {
12
+ class I {
13
13
  // The constructor is private to prevent direct construction calls
14
14
  // with the `new` operator
15
15
  constructor() {
16
16
  this.alreadySet = !1;
17
17
  }
18
18
  static getInstance() {
19
- return k.instance || (k.instance = new k()), k.instance;
19
+ return I.instance || (I.instance = new I()), I.instance;
20
20
  }
21
21
  /**
22
22
  * Method to set the license key for the application.
@@ -37,7 +37,7 @@ class k {
37
37
  function B(p) {
38
38
  return p && p.type === "TreeRow";
39
39
  }
40
- function V(p) {
40
+ function $(p) {
41
41
  return p && p.type === "AreaModelTree";
42
42
  }
43
43
  class _ {
@@ -60,25 +60,25 @@ class _ {
60
60
  );
61
61
  }
62
62
  }
63
- class D {
63
+ class F {
64
64
  constructor(e = ">", t = "", s = []) {
65
65
  this.content = e, this.style = t, this.classes = s;
66
66
  }
67
67
  }
68
68
  class Z {
69
- constructor(e = new D(
69
+ constructor(e = new F(
70
70
  ">",
71
71
  "transform: rotate(90deg) translate(66%, -66%); transform-origin: 0 0;",
72
72
  ["gt-table-tree-arrow-expanded"]
73
- ), t = new D(
73
+ ), t = new F(
74
74
  ">",
75
75
  "",
76
76
  ["ge-table-tree-arrow-collapsed"]
77
- ), s = new D(
77
+ ), s = new F(
78
78
  ">",
79
79
  "color:transparent;",
80
80
  ["gt-table-tree-arrow-hidden"]
81
- ), o = new D(
81
+ ), o = new F(
82
82
  "↕",
83
83
  "",
84
84
  ["gt-table-tree-arrow-expanded-all"]
@@ -87,7 +87,7 @@ class Z {
87
87
  }
88
88
  }
89
89
  class Q {
90
- constructor(e = new D("↑", "", ["ge-header-sorted-asc"]), t = new D("↓", "", ["ge-header-sorted-desc"]), s = new D("↑", "color:transparent;", [])) {
90
+ constructor(e = new F("↑", "", ["ge-header-sorted-asc"]), t = new F("↓", "", ["ge-header-sorted-desc"]), s = new F("↑", "color:transparent;", [])) {
91
91
  this.iconAsc = e, this.iconDesc = t, this.iconPlaceholder = s;
92
92
  }
93
93
  }
@@ -177,12 +177,12 @@ class ne {
177
177
  return this.domService.appendChild(e.child, a), a;
178
178
  }
179
179
  addColumnDiv(e) {
180
- const { parent: t, geo: s, rowIndex: o = -1, columnIndex: i = -1, areaIdent: r, sideIdent: l, text: a = "", treeArrow: n, tableOptions: c, checkedType: h = void 0, sortState: d } = e, u = c == null ? void 0 : c.treeOptions, g = c == null ? void 0 : c.showCheckboxWihoutExtraColumn, b = this.domService.createElement("div");
180
+ const { parent: t, geo: s, rowIndex: o = -1, columnIndex: i = -1, areaIdent: r, sideIdent: l, text: a = "", treeArrow: n, tableOptions: c, checkedType: h = void 0, sortState: d } = e, m = c == null ? void 0 : c.treeOptions, g = c == null ? void 0 : c.showCheckboxWihoutExtraColumn, b = this.domService.createElement("div");
181
181
  this.domService.addClass(b, "ge-table-col-div"), g && this.domService.addClass(b, "ge-with-checkbox"), this.domService.addClass(b, `ge-table-col-div-${s.index}`), this.domService.setAttribute(b, "data-col-index", `${s.index}`), this.domService.setAttribute(b, "data-row-index", `${o}`), this.domService.setAttribute(b, "data-area", `${r}`);
182
182
  const f = ((s == null ? void 0 : s.index) ?? 0) % 2 === 0 ? "even" : "odd";
183
- if (r === "body" && l === "center" && this.domService.addClass(b, `ge-table-column-${f}`), this.domService.setStyle(b, "display", "clip"), this.domService.setStyle(b, "position", "absolute"), this.domService.setStyle(b, "left", `${s.left}px`), this.domService.setStyle(b, "top", `${s.top}px`), this.domService.setStyle(b, "width", `${s.width}px`), this.domService.setStyle(b, "height", `${s.height}px`), n && n !== "none" && (this.domService.addClass(b, "ge-table-col-tree"), this.addArrowDiv(b, n, u, o, i, r)), g && i === 0 && h && this.addCheckboxToDiv(b, h, r, o), a) {
184
- const m = n !== "none" && i === 0;
185
- this.addLabelDiv(b, a, m, o, i, r);
183
+ if (r === "body" && l === "center" && this.domService.addClass(b, `ge-table-column-${f}`), this.domService.setStyle(b, "display", "clip"), this.domService.setStyle(b, "position", "absolute"), this.domService.setStyle(b, "left", `${s.left}px`), this.domService.setStyle(b, "top", `${s.top}px`), this.domService.setStyle(b, "width", `${s.width}px`), this.domService.setStyle(b, "height", `${s.height}px`), n && n !== "none" && (this.domService.addClass(b, "ge-table-col-tree"), this.addArrowDiv(b, n, m, o, i, r)), g && i === 0 && h && this.addCheckboxToDiv(b, h, r, o), a) {
184
+ const u = n !== "none" && i === 0;
185
+ this.addLabelDiv(b, a, u, o, i, r);
186
186
  }
187
187
  return d && this.addSortedIcon(b, d, c == null ? void 0 : c.sortedOptions, i), this.domService.appendChild(t, b), b;
188
188
  }
@@ -536,29 +536,129 @@ class pe {
536
536
  return s * ("" + e).localeCompare("" + t);
537
537
  }
538
538
  }
539
- class F extends he {
539
+ class D extends he {
540
+ /**
541
+ * Creates an instance of AreaModelObjectArray.
542
+ *
543
+ * @param {AreaIdent} areaIdent - Identifies which area of the table this model represents ('header', 'body', or 'footer')
544
+ * @param {T[]} rows - The array of objects that represent the rows in this area
545
+ * @param {number} defaultRowHeight - The default height for rows in this area (in pixels)
546
+ * @param {ColumnDefIf[]} [columnDefs=[]] - Definitions for the columns in this area
547
+ * @param {string} [selectedRowClass='ge-selected-row'] - CSS class to apply to selected rows
548
+ * @param {string} [focusedRowClass='ge-focused-row'] - CSS class to apply to the focused row
549
+ *
550
+ * @example
551
+ * const rows = [
552
+ * { id: 1, name: 'John', age: 30 },
553
+ * { id: 2, name: 'Jane', age: 25 }
554
+ * ];
555
+ *
556
+ * const columnDefs = [
557
+ * { property: 'id', headerLabel: 'ID', width: 50 },
558
+ * { property: 'name', headerLabel: 'Name', width: 150 },
559
+ * { property: 'age', headerLabel: 'Age', width: 100 }
560
+ * ];
561
+ *
562
+ * const bodyAreaModel = new AreaModelObjectArray(
563
+ * 'body',
564
+ * rows,
565
+ * 30,
566
+ * columnDefs
567
+ * );
568
+ */
540
569
  constructor(e, t, s, o = [], i = "ge-selected-row", r = "ge-focused-row") {
541
570
  super(e, o, s), this.areaIdent = e, this.rows = t, this.defaultRowHeight = s, this.columnDefs = o, this.selectedRowClass = i, this.focusedRowClass = r, this.sorterService = new pe(), this._focusedRowIndex = 0, this.filteredRows = [...t], this.properties = o.map((l) => l.property);
542
571
  }
572
+ /**
573
+ * Gets the index of the currently focused row.
574
+ *
575
+ * @returns {number} The index of the focused row
576
+ *
577
+ * @example
578
+ * const focusedRowIndex = bodyAreaModel.getFocusedRowIndex();
579
+ * console.log(`The focused row is at index ${focusedRowIndex}`);
580
+ */
543
581
  getFocusedRowIndex() {
544
582
  return this._focusedRowIndex;
545
583
  }
584
+ /**
585
+ * Sets the index of the focused row.
586
+ * This will apply the focused row styling to the specified row.
587
+ *
588
+ * @param {number} value - The index of the row to focus
589
+ *
590
+ * @example
591
+ * // Focus the second row (index 1)
592
+ * bodyAreaModel.setFocusedRowIndex(1);
593
+ */
546
594
  setFocusedRowIndex(e) {
547
595
  this._focusedRowIndex = e;
548
596
  }
597
+ /**
598
+ * Replaces the current rows array with a new one.
599
+ * This also resets the filtered rows to match the new rows array.
600
+ *
601
+ * @param {T[]} rows - The new array of row objects
602
+ *
603
+ * @example
604
+ * // Replace the current rows with new data
605
+ * const newRows = [
606
+ * { id: 4, name: 'Alice', age: 35 },
607
+ * { id: 5, name: 'Charlie', age: 45 }
608
+ * ];
609
+ * bodyAreaModel.setRows(newRows);
610
+ */
549
611
  setRows(e) {
550
612
  this.rows = e, this.filteredRows = [...e];
551
613
  }
614
+ /**
615
+ * Filters both the original rows and filtered rows arrays using the provided predicate function.
616
+ * Unlike `externalFilterChanged`, this method permanently modifies the original rows array.
617
+ *
618
+ * @param {(row: T) => boolean} predict - A function that returns true for rows to keep and false for rows to filter out
619
+ *
620
+ * @example
621
+ * // Remove all rows where age is less than 30
622
+ * bodyAreaModel.filterRowsByPredict(row => row.age >= 30);
623
+ */
552
624
  filterRowsByPredict(e) {
553
625
  this.rows = this.rows.filter(e), this.filteredRows = this.filteredRows.filter(e);
554
626
  }
555
627
  /**
556
- * return row count of filtered rows
628
+ * Returns the number of rows in the filtered rows array.
629
+ * This is used to determine how many rows should be rendered in the table.
630
+ *
631
+ * @returns {number} The number of rows in the filtered rows array
632
+ *
633
+ * @example
634
+ * const rowCount = bodyAreaModel.getRowCount();
635
+ * console.log(`The table has ${rowCount} rows`);
557
636
  */
558
637
  getRowCount() {
559
638
  var e;
560
639
  return ((e = this.filteredRows) == null ? void 0 : e.length) ?? 0;
561
640
  }
641
+ /**
642
+ * Gets the value at the specified row and column indices.
643
+ * This method handles tree rows and nested properties.
644
+ *
645
+ * @param {number} rowIndex - The index of the row
646
+ * @param {number} columnIndex - The index of the column
647
+ * @returns {any} The value at the specified cell, or an empty string if not found
648
+ *
649
+ * @example
650
+ * // Get the value in the first row, second column
651
+ * const value = bodyAreaModel.getValueAt(0, 1);
652
+ * console.log(`The value is: ${value}`);
653
+ *
654
+ * @example
655
+ * // Iterate through all cells in a row
656
+ * const rowIndex = 0;
657
+ * for (let colIndex = 0; colIndex < columnDefs.length; colIndex++) {
658
+ * const value = bodyAreaModel.getValueAt(rowIndex, colIndex);
659
+ * console.log(`Cell (${rowIndex}, ${colIndex}): ${value}`);
660
+ * }
661
+ */
562
662
  getValueAt(e, t) {
563
663
  const s = this.properties[t];
564
664
  let o = this.filteredRows[e];
@@ -567,46 +667,176 @@ class F extends he {
567
667
  /**
568
668
  * Retrieves the filtered and sorted rows from the dataset.
569
669
  * These rows are used for rendering the table.
670
+ * Unlike `getAllRows()`, this method returns only the rows that match any applied filters.
570
671
  *
571
- * @return {T[]} An array containing the filtered (and sorted) rows.
672
+ * @returns {T[]} An array containing the filtered (and sorted) rows
673
+ *
674
+ * @example
675
+ * // Get all filtered rows
676
+ * const filteredRows = bodyAreaModel.getFilteredRows();
677
+ *
678
+ * // Count rows that match a certain condition
679
+ * const adultsCount = filteredRows.filter(row => row.age >= 18).length;
572
680
  */
573
681
  getFilteredRows() {
574
682
  return this.filteredRows;
575
683
  }
684
+ /**
685
+ * Returns the original, unfiltered array of rows.
686
+ * This can be useful when you need to access all data regardless of any applied filters.
687
+ *
688
+ * @returns {T[]} The original array of row objects
689
+ *
690
+ * @example
691
+ * // Get all rows, including those filtered out
692
+ * const allRows = bodyAreaModel.getAllRows();
693
+ *
694
+ * // Calculate average age across all rows
695
+ * const totalAge = allRows.reduce((sum, row) => sum + row.age, 0);
696
+ * const averageAge = totalAge / allRows.length;
697
+ */
576
698
  getAllRows() {
577
699
  return this.rows;
578
700
  }
579
701
  /**
580
702
  * Returns the first row from the filtered rows that matches the given criteria based on the provided predicate function.
703
+ * This method only searches within the filtered rows, not the original rows array.
581
704
  *
582
705
  * @param {Partial<T>} criteria - A partial object containing the search criteria
583
706
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
584
707
  * and returns true if the row matches the criteria
585
708
  * @returns {T | undefined} The first matching row, or undefined if no match is found
709
+ *
710
+ * @example
711
+ * // Find a user by name in the filtered rows
712
+ * const criteria = { name: 'John' };
713
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
714
+ * criteria,
715
+ * (criteria, row) => row.name === criteria.name
716
+ * );
717
+ *
718
+ * @example
719
+ * // Find a user by age range in the filtered rows
720
+ * const criteria = { minAge: 25, maxAge: 35 };
721
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
722
+ * criteria,
723
+ * (criteria, row) => row.age >= criteria.minAge && row.age <= criteria.maxAge
724
+ * );
586
725
  */
587
726
  findRowFromFilteredRowsByAllCriteria(e, t) {
588
727
  return this.getFilteredRows().find((s) => t(e, s));
589
728
  }
590
729
  /**
591
730
  * Searches through all rows to find a row that matches the given criteria based on the predicate function.
731
+ * This method searches within the original rows array, including rows that may have been filtered out.
592
732
  *
593
733
  * @param {Partial<T>} criteria - A partial object containing the search criteria
594
734
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
595
735
  * and returns true if the row matches the criteria
596
736
  * @returns {T | undefined} The first matching row from all rows, or undefined if no match is found
737
+ *
738
+ * @example
739
+ * // Find a user by ID in all rows
740
+ * const criteria = { id: 42 };
741
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
742
+ * criteria,
743
+ * (criteria, row) => row.id === criteria.id
744
+ * );
745
+ *
746
+ * @example
747
+ * // Find a user with a specific property value in all rows
748
+ * const criteria = { department: 'Engineering', role: 'Manager' };
749
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
750
+ * criteria,
751
+ * (criteria, row) => row.department === criteria.department && row.role === criteria.role
752
+ * );
597
753
  */
598
754
  findRowFromAllRowsByAllCriteria(e, t) {
599
755
  return this.getAllRows().find((s) => t(e, s));
600
756
  }
757
+ /**
758
+ * Returns the height of the row at the specified index.
759
+ * This implementation always returns the default row height.
760
+ * Override this method in subclasses to support variable row heights.
761
+ *
762
+ * @param {number} _rowIndex - The index of the row (unused in this implementation)
763
+ * @returns {number} The height of the row in pixels
764
+ *
765
+ * @example
766
+ * const rowHeight = bodyAreaModel.getRowHeight(0);
767
+ * console.log(`The first row has a height of ${rowHeight}px`);
768
+ */
601
769
  getRowHeight(e) {
602
770
  return this.defaultRowHeight;
603
771
  }
772
+ /**
773
+ * Returns the row object at the specified index from the filtered rows array.
774
+ * This method overrides the parent class implementation.
775
+ *
776
+ * @param {number} rowIndex - The index of the row to retrieve
777
+ * @returns {any} The row object at the specified index, or undefined if the index is out of bounds
778
+ *
779
+ * @example
780
+ * // Get the first row object
781
+ * const row = bodyAreaModel.getRowByIndex(0);
782
+ * console.log('First row:', row);
783
+ *
784
+ * @example
785
+ * // Iterate through all rows
786
+ * for (let i = 0; i < bodyAreaModel.getRowCount(); i++) {
787
+ * const row = bodyAreaModel.getRowByIndex(i);
788
+ * console.log(`Row ${i}:`, row);
789
+ * }
790
+ */
604
791
  getRowByIndex(e) {
605
792
  return this.filteredRows[e];
606
793
  }
794
+ /**
795
+ * Applies an external filter function to the rows array.
796
+ * This method updates the filtered rows array without modifying the original rows array.
797
+ *
798
+ * @param {FilterFunction<any>} predictFn - A function that returns true for rows to keep and false for rows to filter out
799
+ *
800
+ * @example
801
+ * // Filter rows where age is greater than 30
802
+ * bodyAreaModel.externalFilterChanged(row => row.age > 30);
803
+ *
804
+ * @example
805
+ * // Filter rows based on a search term
806
+ * const searchTerm = 'john';
807
+ * bodyAreaModel.externalFilterChanged(row =>
808
+ * row.name.toLowerCase().includes(searchTerm.toLowerCase())
809
+ * );
810
+ *
811
+ * @example
812
+ * // Clear all filters
813
+ * bodyAreaModel.externalFilterChanged(() => true);
814
+ */
607
815
  externalFilterChanged(e) {
608
816
  this.filteredRows = this.rows ? this.rows.filter(e) : [];
609
817
  }
818
+ /**
819
+ * Sorts the filtered rows based on the provided sort items.
820
+ * This method supports sorting by multiple columns with different sort directions.
821
+ *
822
+ * @param {SortItem[]} sortItems - An array of sort items, each containing a column index and sort state
823
+ * @returns {boolean} Always returns true to indicate sorting was performed
824
+ *
825
+ * @example
826
+ * // Sort by age in ascending order
827
+ * bodyAreaModel.doSort([{ columnIndex: 2, sortState: 'asc' }]);
828
+ *
829
+ * @example
830
+ * // Sort by name in descending order, then by age in ascending order
831
+ * bodyAreaModel.doSort([
832
+ * { columnIndex: 1, sortState: 'desc' },
833
+ * { columnIndex: 2, sortState: 'asc' }
834
+ * ]);
835
+ *
836
+ * @example
837
+ * // Clear sorting
838
+ * bodyAreaModel.doSort([{ columnIndex: 0, sortState: 'none' }]);
839
+ */
610
840
  doSort(e) {
611
841
  for (const t of e) {
612
842
  const { columnIndex: s, sortState: o } = t, i = o === "asc" ? 1 : o === "desc" ? -1 : 0, r = this.properties[s];
@@ -614,20 +844,110 @@ class F extends he {
614
844
  }
615
845
  return !0;
616
846
  }
847
+ /**
848
+ * Sorts the filtered rows using a custom comparator function.
849
+ * This method provides more flexibility than `doSort()` for complex sorting logic.
850
+ *
851
+ * @param {(a: T, b: T) => number} compareFn - A function that compares two rows and returns a number:
852
+ * - Negative if a should come before b
853
+ * - Positive if a should come after b
854
+ * - Zero if they are equivalent for sorting purposes
855
+ *
856
+ * @example
857
+ * // Sort by name length
858
+ * bodyAreaModel.sort((a, b) => a.name.length - b.name.length);
859
+ *
860
+ * @example
861
+ * // Sort by a computed value
862
+ * bodyAreaModel.sort((a, b) => {
863
+ * const scoreA = a.wins * 3 + a.draws;
864
+ * const scoreB = b.wins * 3 + b.draws;
865
+ * return scoreB - scoreA; // Descending order
866
+ * });
867
+ */
617
868
  sort(e) {
618
869
  this.filteredRows = this.filteredRows.sort(e);
619
870
  }
871
+ /**
872
+ * Gets a value from an object using a property path.
873
+ * This method supports accessing nested properties using dot notation (e.g., 'person.name').
874
+ *
875
+ * @param {T} t - The object to get the value from
876
+ * @param {string} property - The property path to access (e.g., 'name' or 'person.contact.email')
877
+ * @returns {any} The value at the specified property path, or undefined if not found
878
+ *
879
+ * @example
880
+ * const user = { id: 1, name: 'John', contact: { email: 'john@example.com' } };
881
+ *
882
+ * // Access simple property
883
+ * const name = bodyAreaModel.getValueByT(user, 'name');
884
+ * console.log(name); // 'John'
885
+ *
886
+ * // Access nested property
887
+ * const email = bodyAreaModel.getValueByT(user, 'contact.email');
888
+ * console.log(email); // 'john@example.com'
889
+ */
620
890
  getValueByT(e, t) {
621
891
  if (e && t)
622
892
  return t.includes(".") ? this.getPropertyValue(e, t.split(".")) : e[t];
623
893
  }
894
+ /**
895
+ * Changes the order of columns by moving a column from one position to another.
896
+ * This method updates both the properties array and calls the parent class implementation.
897
+ *
898
+ * @param {number} sourceColumnIndex - The index of the column to move
899
+ * @param {number} targetColumnIndex - The index where the column should be moved to
900
+ *
901
+ * @example
902
+ * // Move the second column (index 1) to the fourth position (index 3)
903
+ * bodyAreaModel.changeColumnOrder(1, 3);
904
+ *
905
+ * @example
906
+ * // Move the last column to the first position
907
+ * const lastIndex = bodyAreaModel.columnDefs.length - 1;
908
+ * bodyAreaModel.changeColumnOrder(lastIndex, 0);
909
+ */
624
910
  changeColumnOrder(e, t) {
625
911
  this.arrayMove(this.properties, e, t), super.changeColumnOrder(e, t);
626
912
  }
913
+ /**
914
+ * Gets the custom CSS classes that should be applied to a cell.
915
+ * This method extends the parent class implementation to add selection and focus classes.
916
+ *
917
+ * @param {number} rowIndex - The index of the row
918
+ * @param {number} _columnIndex - The index of the column (unused in this implementation)
919
+ * @returns {string[]} An array of CSS class names to apply to the cell
920
+ *
921
+ * @example
922
+ * // Get the CSS classes for a cell
923
+ * const classes = bodyAreaModel.getCustomClassesAt(1, 2);
924
+ * console.log('CSS classes:', classes);
925
+ *
926
+ * @example
927
+ * // Apply the classes to a cell element
928
+ * const cellElement = document.createElement('div');
929
+ * const classes = bodyAreaModel.getCustomClassesAt(rowIndex, columnIndex);
930
+ * cellElement.classList.add(...classes);
931
+ */
627
932
  getCustomClassesAt(e, t) {
628
933
  const s = super.getCustomClassesAt(e, t);
629
934
  return this.getRowByIndex(e).selected && s.push(this.selectedRowClass), this._focusedRowIndex === e && s.push(this.focusedRowClass), s;
630
935
  }
936
+ /**
937
+ * Creates a comparator function for sorting rows based on a property and sort direction.
938
+ * This method supports custom sort comparators defined in column definitions.
939
+ *
940
+ * @param {string} property - The property to sort by
941
+ * @param {number} f - The sort direction factor: 1 for ascending, -1 for descending, 0 for no sorting
942
+ * @returns {(a: T, b: T) => number} A comparator function that compares two rows
943
+ *
944
+ * @example
945
+ * // Create a comparator for sorting by name in ascending order
946
+ * const comparator = bodyAreaModel.genericFlatTableSortComparator('name', 1);
947
+ *
948
+ * // Sort the rows using the comparator
949
+ * const sortedRows = [...bodyAreaModel.getFilteredRows()].sort(comparator);
950
+ */
631
951
  genericFlatTableSortComparator(e, t) {
632
952
  const s = this.columnDefs.find((o) => o.property === e);
633
953
  return (o, i) => {
@@ -635,6 +955,16 @@ class F extends he {
635
955
  return s != null && s.sortComparator ? t * s.sortComparator(r, l, o, i, t) : this.sorterService.genericSortComparator(r, l, t);
636
956
  };
637
957
  }
958
+ /**
959
+ * Recursively gets a value from an object using an array of property names.
960
+ * This is a helper method used by `getValueByT` to access nested properties.
961
+ *
962
+ * @param {any} o - The object to get the value from
963
+ * @param {string[]} props - An array of property names representing the path to the value
964
+ * @returns {any} The value at the specified property path, or undefined if not found
965
+ *
966
+ * @private
967
+ */
638
968
  getPropertyValue(e, t) {
639
969
  const s = t.shift(), o = e[s];
640
970
  return o && t.length ? this.getPropertyValue(o, t) : o;
@@ -645,41 +975,302 @@ class ge {
645
975
  this.tableScope = e;
646
976
  }
647
977
  /**
648
- * Updates the cells in the table based on the provided events.
978
+ * Updates the cells in the table with the provided cell update events.
649
979
  *
650
- * @param {TableCellUpdateEventIf[]} events - The array of events representing the updates to perform on the cells.
651
- * @param {boolean} [repaintAll=false] - Optional parameter indicating whether to repaint all cells or not. Default value is false. If true, the full table will be rendered. If false, the table cell will be rendered immediately.
980
+ * This method allows you to update specific cells in the table without requiring a full table repaint,
981
+ * which can significantly improve performance when updating large tables frequently.
652
982
  *
653
- * @return {void} - This method doesn't return anything.
983
+ * @param {TableCellUpdateEventIf[]} events - An array of cell update events, each defining a single cell update operation.
984
+ * Each event must specify:
985
+ * - area: The table area to update ('header', 'body', or 'footer')
986
+ * - rowIndex: The row index of the cell to update
987
+ * - columnIndex: The column index of the cell to update
988
+ * - value: The new value to set for the cell
989
+ * - cssClasses: Optional object mapping CSS class names to boolean values
990
+ * (true to add the class, false to remove it)
991
+ *
992
+ * @param {boolean} [repaintAll=false] - Whether to repaint the entire table after updating cells.
993
+ * - If true: All cells will be repainted after updating (slower but ensures visual consistency)
994
+ * - If false: Only the modified cells will be repainted (faster, recommended for frequent updates)
995
+ *
996
+ * @returns {void}
997
+ *
998
+ * @example
999
+ * // Update a single cell with a new value and CSS classes
1000
+ * tableApi.updateCells([{
1001
+ * area: 'body',
1002
+ * rowIndex: 3,
1003
+ * columnIndex: 2,
1004
+ * value: 42,
1005
+ * cssClasses: {
1006
+ * 'highlight': true, // Add 'highlight' class
1007
+ * 'error': false // Remove 'error' class if present
1008
+ * }
1009
+ * }]);
1010
+ *
1011
+ * @example
1012
+ * // Update multiple cells at once
1013
+ * tableApi.updateCells([
1014
+ * {
1015
+ * area: 'body',
1016
+ * rowIndex: 1,
1017
+ * columnIndex: 1,
1018
+ * value: 'New Value 1',
1019
+ * cssClasses: { 'updated': true }
1020
+ * },
1021
+ * {
1022
+ * area: 'body',
1023
+ * rowIndex: 2,
1024
+ * columnIndex: 3,
1025
+ * value: 'New Value 2',
1026
+ * cssClasses: { 'updated': true }
1027
+ * }
1028
+ * ]);
1029
+ *
1030
+ * @example
1031
+ * // Update cells and repaint the entire table
1032
+ * tableApi.updateCells([
1033
+ * { area: 'body', rowIndex: 0, columnIndex: 0, value: 'Hello', cssClasses: { 'bg-green-0': true } },
1034
+ * { area: 'body', rowIndex: 1, columnIndex: 1, value: 'World', cssClasses: { 'bg-red-0': true } }
1035
+ * ], true);
1036
+ *
1037
+ * @example
1038
+ * // High-performance animation example (update without full repaint)
1039
+ * function animateCell() {
1040
+ * const value = Math.sin(Date.now() / 1000) * 50;
1041
+ * const cssClasses = {
1042
+ * 'positive': value > 0,
1043
+ * 'negative': value < 0
1044
+ * };
1045
+ *
1046
+ * tableApi.updateCells([{
1047
+ * area: 'body',
1048
+ * rowIndex: 0,
1049
+ * columnIndex: 0,
1050
+ * value: Math.round(value),
1051
+ * cssClasses
1052
+ * }]);
1053
+ *
1054
+ * requestAnimationFrame(animateCell);
1055
+ * }
1056
+ * animateCell();
654
1057
  */
655
1058
  updateCells(e, t = !1) {
656
1059
  this.tableScope.updateCells(e, t);
657
1060
  }
658
1061
  /**
659
- * Notifies that the external filter has changed.
1062
+ * Notifies the table that an external filter has been changed and needs to be applied.
660
1063
  *
661
- * @return {void}
1064
+ * This method is used when an external filter condition (defined by `tableOptions.externalFilterFunction`)
1065
+ * has changed and the table needs to refresh its display to reflect the new filtering criteria.
1066
+ *
1067
+ * When called, this method:
1068
+ * 1. Applies the external filter function to all rows
1069
+ * 2. Clears the current selection (by default)
1070
+ * 3. Scrolls to the top of the table
1071
+ * 4. Recalculates table dimensions
1072
+ * 5. Repaints the table to display only the filtered rows
1073
+ *
1074
+ * @example
1075
+ * ```typescript
1076
+ * // Define an external filter function in your table options
1077
+ * const tableOptions = {
1078
+ * externalFilterFunction: (row: MyRowType) => {
1079
+ * // Return true to include the row, false to filter it out
1080
+ * return row.status === 'active';
1081
+ * }
1082
+ * };
1083
+ *
1084
+ * // Initialize your table with these options
1085
+ * const tableApi = new TableApi(tableScope);
1086
+ *
1087
+ * // Later, when filter criteria change (e.g., in a search input handler)
1088
+ * function onFilterTextChanged() {
1089
+ * // Update the filter function if needed
1090
+ * tableOptions.externalFilterFunction = (row: MyRowType) => {
1091
+ * return row.name.includes(searchText);
1092
+ * };
1093
+ *
1094
+ * // Apply the updated filter
1095
+ * tableApi.externalFilterChanged();
1096
+ * }
1097
+ * ```
1098
+ *
1099
+ * @returns {void}
1100
+ * @see TableScope.externalFilterChanged
662
1101
  */
663
1102
  externalFilterChanged() {
664
1103
  this.tableScope.externalFilterChanged();
665
1104
  }
666
1105
  /**
667
- * Scrolls the table body to the specified pixel coordinates.
1106
+ * Scrolls the table content to the specified pixel coordinates.
668
1107
  *
669
- * @param {number} px - The horizontal pixel coordinate to scroll to. Defaults to 0.
670
- * @param {number} py - The vertical pixel coordinate to scroll to. Defaults to 0.
671
- * @return {void}
1108
+ * This method allows programmatic scrolling of the table viewport to exact pixel positions.
1109
+ * It delegates the scrolling operation to the underlying TableScope instance.
1110
+ *
1111
+ * @param {number} px - The horizontal pixel coordinate to scroll to. Defaults to 0 (leftmost position).
1112
+ * @param {number} py - The vertical pixel coordinate to scroll to. Defaults to 0 (topmost position).
1113
+ * @returns {void}
1114
+ *
1115
+ * @example
1116
+ * // Scroll to the top-left corner of the table
1117
+ * tableApi.scrollToPixel(0, 0);
1118
+ *
1119
+ * @example
1120
+ * // Scroll 200 pixels horizontally and 150 pixels vertically
1121
+ * tableApi.scrollToPixel(200, 150);
1122
+ *
1123
+ * @example
1124
+ * // Scroll only vertically, keeping the current horizontal position
1125
+ * tableApi.scrollToPixel(undefined, 300);
1126
+ *
1127
+ * @example
1128
+ * // Example in a component that needs precise scrolling control
1129
+ * class TableScroller {
1130
+ * private tableApi: TableApi;
1131
+ *
1132
+ * constructor(tableApi: TableApi) {
1133
+ * this.tableApi = tableApi;
1134
+ * }
1135
+ *
1136
+ * scrollToPosition(x: number, y: number) {
1137
+ * // Scroll to exact pixel coordinates
1138
+ * this.tableApi.scrollToPixel(x, y);
1139
+ * }
1140
+ *
1141
+ * scrollHalfway() {
1142
+ * const tableModel = this.tableApi.getTableModel();
1143
+ * const totalWidth = tableModel.getContentWidthInPixel();
1144
+ * const totalHeight = tableModel.getContentHeightInPixel();
1145
+ *
1146
+ * // Scroll to the middle of the table content
1147
+ * this.tableApi.scrollToPixel(totalWidth / 2, totalHeight / 2);
1148
+ * }
1149
+ * }
1150
+ *
1151
+ * @example
1152
+ * // Advanced usage with animated scrolling
1153
+ * class SmoothScroller {
1154
+ * private tableApi: TableApi;
1155
+ * private animationFrameId: number | null = null;
1156
+ *
1157
+ * constructor(tableApi: TableApi) {
1158
+ * this.tableApi = tableApi;
1159
+ * }
1160
+ *
1161
+ * smoothScrollTo(targetX: number, targetY: number, duration: number = 500) {
1162
+ * // Cancel any ongoing animation
1163
+ * if (this.animationFrameId !== null) {
1164
+ * cancelAnimationFrame(this.animationFrameId);
1165
+ * }
1166
+ *
1167
+ * const startTime = performance.now();
1168
+ * const startX = this.tableApi.getTableScope().getScrollLeft();
1169
+ * const startY = this.tableApi.getTableScope().getScrollTop();
1170
+ * const distanceX = targetX - startX;
1171
+ * const distanceY = targetY - startY;
1172
+ *
1173
+ * const step = (currentTime: number) => {
1174
+ * const elapsed = currentTime - startTime;
1175
+ * const progress = Math.min(elapsed / duration, 1);
1176
+ *
1177
+ * // Use easing function for smooth animation
1178
+ * const easeProgress = 1 - Math.pow(1 - progress, 3); // Cubic ease-out
1179
+ *
1180
+ * const currentX = startX + distanceX * easeProgress;
1181
+ * const currentY = startY + distanceY * easeProgress;
1182
+ *
1183
+ * this.tableApi.scrollToPixel(currentX, currentY);
1184
+ *
1185
+ * if (progress < 1) {
1186
+ * this.animationFrameId = requestAnimationFrame(step);
1187
+ * } else {
1188
+ * this.animationFrameId = null;
1189
+ * }
1190
+ * };
1191
+ *
1192
+ * this.animationFrameId = requestAnimationFrame(step);
1193
+ * }
1194
+ *
1195
+ * cancelAnimation() {
1196
+ * if (this.animationFrameId !== null) {
1197
+ * cancelAnimationFrame(this.animationFrameId);
1198
+ * this.animationFrameId = null;
1199
+ * }
1200
+ * }
1201
+ * }
1202
+ *
1203
+ * @see {@link scrollToIndex} - For scrolling based on row and column indices
1204
+ * @see {@link ensureRowIsVisible} - For scrolling to make a specific row visible
672
1205
  */
673
1206
  scrollToPixel(e = 0, t = 0) {
674
1207
  this.tableScope.scrollToPixel(e, t);
675
1208
  }
676
1209
  /**
677
- * Scrolls to the specified index in both horizontal and vertical directions.
1210
+ * Scrolls the table to display the specified row and column indices at the top-left corner of the viewport.
678
1211
  *
679
- * @param {number} indexX - The index of the column to scroll to in the horizontal direction. Default is 0.
680
- * @param {number} indexY - The index of the row to scroll to in the vertical direction. Default is 0.
1212
+ * This method allows programmatic scrolling to a specific position in the table grid based on row and column indices.
1213
+ * It uses the underlying TableScope's scrolling mechanism to navigate to the target location.
681
1214
  *
682
- * @return undefined
1215
+ * @param {number} indexX - The horizontal index (column) to scroll to. Defaults to 0 (leftmost column).
1216
+ * @param {number} indexY - The vertical index (row) to scroll to. Defaults to 0 (topmost row).
1217
+ * @returns {void}
1218
+ *
1219
+ * @example
1220
+ * // Scroll to the 5th row, keeping the current horizontal scroll position
1221
+ * tableApi.scrollToIndex(0, 5);
1222
+ *
1223
+ * @example
1224
+ * // Scroll to column 3, row 10
1225
+ * tableApi.scrollToIndex(3, 10);
1226
+ *
1227
+ * @example
1228
+ * // Example in a component that needs to navigate to specific content
1229
+ * class TableNavigator {
1230
+ * private tableApi: TableApi;
1231
+ *
1232
+ * constructor(tableApi: TableApi) {
1233
+ * this.tableApi = tableApi;
1234
+ * }
1235
+ *
1236
+ * goToCell(columnIndex: number, rowIndex: number) {
1237
+ * // Navigate directly to the specified cell position
1238
+ * this.tableApi.scrollToIndex(columnIndex, rowIndex);
1239
+ *
1240
+ * // Optional: Select the cell after navigating to it
1241
+ * const selectionModel = this.tableApi.getSelectionModel();
1242
+ * if (selectionModel) {
1243
+ * selectionModel.selectCell(rowIndex, columnIndex);
1244
+ * }
1245
+ * }
1246
+ * }
1247
+ *
1248
+ * @example
1249
+ * // Advanced usage with search functionality
1250
+ * class TableSearcher {
1251
+ * findAndScrollToMatch(searchTerm: string) {
1252
+ * const tableModel = this.tableApi.getTableModel();
1253
+ * const bodyModel = tableModel.getAreaModel('body');
1254
+ *
1255
+ * // Search for the term in the table data
1256
+ * for (let row = 0; row < bodyModel.getRowCount(); row++) {
1257
+ * for (let col = 0; col < tableModel.getColumnCount(); col++) {
1258
+ * const cellContent = bodyModel.getValueAt(row, col)?.toString() || '';
1259
+ *
1260
+ * if (cellContent.includes(searchTerm)) {
1261
+ * // Found a match, scroll to it
1262
+ * this.tableApi.scrollToIndex(col, row);
1263
+ * return true;
1264
+ * }
1265
+ * }
1266
+ * }
1267
+ *
1268
+ * return false; // No match found
1269
+ * }
1270
+ * }
1271
+ *
1272
+ * @see {@link scrollToPixel} - For scrolling to specific pixel coordinates
1273
+ * @see {@link ensureRowIsVisible} - For scrolling to make a specific row visible
683
1274
  */
684
1275
  scrollToIndex(e = 0, t = 0) {
685
1276
  this.tableScope.scrollToIndex(e, t);
@@ -740,19 +1331,71 @@ class ge {
740
1331
  /**
741
1332
  * Repaints the table.
742
1333
  *
743
- * This method calls the repaint method of the tableScope object
744
- * to update and redraw the table based on the latest data.
1334
+ * This method refreshes the visual representation of the table by delegating to the
1335
+ * tableScope's repaint functionality. Use this method whenever the table's visual state
1336
+ * needs to be updated after data changes, selection changes, or any modifications that
1337
+ * affect the rendered output.
1338
+ *
1339
+ * Repainting the table ensures that all visible cells, rows, and styling reflect the
1340
+ * current state of the underlying data model and configuration settings.
1341
+ *
1342
+ * @example
1343
+ * // Update data and repaint the table
1344
+ * const tableApi = new TableApi(tableScope);
1345
+ * tableApi.setRows(newData);
1346
+ * tableApi.repaint();
1347
+ *
1348
+ * @example
1349
+ * // Update selection and repaint to show the visual change
1350
+ * tableApi.getSelectionModel().selectCell(2, 3);
1351
+ * tableApi.repaint();
1352
+ *
1353
+ * @example
1354
+ * // After changing column visibility, repaint to reflect changes
1355
+ * tableApi.setColumnVisible(0, false);
1356
+ * tableApi.repaint();
1357
+ *
1358
+ * @returns {void}
745
1359
  */
746
1360
  repaint() {
747
1361
  this.tableScope.repaint();
748
1362
  }
749
1363
  /**
750
- * Repaints the table scope with hard repaint.
751
- * Repaints the UI by resetting the size of the wrapper div,
752
- * adjusting the containers and rows, and performing additional adjustments
753
- * after scrolling.
1364
+ * Performs a complete repaint of the table by triggering a hard repaint on the underlying table scope.
754
1365
  *
755
- * @return {void}
1366
+ * A hard repaint is more thorough than a regular repaint and performs the following operations:
1367
+ * - Recalculates the height and padding of the table model
1368
+ * - Resets the size of the wrapper div elements
1369
+ * - Adjusts containers and rows positioning
1370
+ * - Makes additional adjustments after scrolling
1371
+ *
1372
+ * Use this method when regular repaint isn't sufficient, such as when:
1373
+ * - Table dimensions have significantly changed
1374
+ * - The structure of data has been modified (rows/columns added or removed)
1375
+ * - The table layout needs complete recalculation
1376
+ * - After major DOM changes affecting the table's container
1377
+ *
1378
+ * @example
1379
+ * // Example 1: Basic usage
1380
+ * tableApi.repaintHard();
1381
+ *
1382
+ * @example
1383
+ * // Example 2: Using after major data changes
1384
+ * tableApi.setRows(newDataSet);
1385
+ * tableApi.repaintHard();
1386
+ *
1387
+ * @example
1388
+ * // Example 3: Using after resizing a container
1389
+ * window.addEventListener('resize', () => {
1390
+ * tableApi.repaintHard();
1391
+ * });
1392
+ *
1393
+ * @example
1394
+ * // Example 4: Using after changing column visibility
1395
+ * tableApi.setColumnVisible(2, false);
1396
+ * tableApi.repaintHard();
1397
+ *
1398
+ * @returns {void} This method doesn't return a value
756
1399
  */
757
1400
  repaintHard() {
758
1401
  this.tableScope.repaintHard();
@@ -768,8 +1411,30 @@ class ge {
768
1411
  this.tableScope.recalcColumnWidths(e);
769
1412
  }
770
1413
  /**
771
- * Clears the current selection of the table.
772
- * The table will be rendered automatically.
1414
+ * Clears the current selection in the table.
1415
+ *
1416
+ * This method removes any selected cells, rows, or columns in the table.
1417
+ * It provides a convenient way to programmatically clear all selections in the table
1418
+ * without having to access the underlying selection model directly.
1419
+ *
1420
+ * When called, this method delegates to the table scope's clearSelection method with
1421
+ * a parameter value of true, which ensures the table is automatically repainted after
1422
+ * the selection is cleared.
1423
+ *
1424
+ * @example
1425
+ * // Clear all selections in the table
1426
+ * tableApi.clearSelection();
1427
+ *
1428
+ * // Example usage in a component
1429
+ * class MyComponent {
1430
+ * @ViewChild('tableComponent') tableComponent: TableComponent;
1431
+ *
1432
+ * resetTableSelection(): void {
1433
+ * if (this.tableComponent?.api) {
1434
+ * this.tableComponent.api.clearSelection();
1435
+ * }
1436
+ * }
1437
+ * }
773
1438
  *
774
1439
  * @returns {void}
775
1440
  */
@@ -777,12 +1442,31 @@ class ge {
777
1442
  this.tableScope.clearSelection(!0);
778
1443
  }
779
1444
  /**
780
- * Sets the selection model for the table scope.
1445
+ * Sets the selection model for the table.
781
1446
  *
782
- * @param {SelectionModel} sm - The selection model to be set.
783
- * @param {boolean} [repaint=true] - Indicates whether the table should be repainted after setting the selection model. Default value is true.
1447
+ * This method allows you to replace the current selection model with a new one,
1448
+ * which controls how cells, rows, or columns can be selected in the table.
784
1449
  *
785
- * @return {void}
1450
+ * @param {SelectionModel} sm - The new selection model to be set. This model defines
1451
+ * the selection behavior including selection type (none, cell, row, column),
1452
+ * selection mode (single, multi), and manages the selected ranges.
1453
+ * @param {boolean} [repaint=true] - Whether to repaint the table after changing the selection model.
1454
+ * Default is true, which immediately reflects the change visually.
1455
+ * Set to false if you want to avoid immediate repainting.
1456
+ *
1457
+ * @example
1458
+ * // Create a new selection model with row selection and multi-select mode
1459
+ * const selectionModel = new SelectionModel("row", "multi");
1460
+ *
1461
+ * // Set the new selection model and repaint the table
1462
+ * tableApi.setSelectionModel(selectionModel);
1463
+ *
1464
+ * // Set a selection model without repainting (if you plan to make more changes)
1465
+ * tableApi.setSelectionModel(selectionModel, false);
1466
+ * // ... make other changes ...
1467
+ * tableApi.repaint(); // Now repaint once
1468
+ *
1469
+ * @returns {void}
786
1470
  */
787
1471
  setSelectionModel(e, t = !0) {
788
1472
  this.tableScope.setSelectionModel(e, t);
@@ -798,9 +1482,36 @@ class ge {
798
1482
  this.tableScope.onActionTriggered(e);
799
1483
  }
800
1484
  /**
801
- * Retrieves the mapping of shortcuts to corresponding action in the current table scope.
1485
+ * Retrieves the shortcut action mapping from the table's shortcut service.
1486
+ *
1487
+ * This method provides access to the keyboard shortcut configuration that defines
1488
+ * which keys trigger specific actions in the table. The mapping contains key-value
1489
+ * pairs where:
1490
+ * - Keys are string representations of keyboard shortcuts (e.g., "ctrl+c", "shift+arrow_down")
1491
+ * - Values are ActionId values representing the corresponding table actions
1492
+ *
1493
+ * This mapping can be useful for:
1494
+ * - Displaying available shortcuts to users
1495
+ * - Creating custom shortcut documentation
1496
+ * - Dynamically checking which actions are available via keyboard
1497
+ * - Extending or integrating with the table's shortcut system
1498
+ *
1499
+ * @returns {ShortcutActionIdMapping} An object mapping shortcut key combinations to their corresponding action IDs.
1500
+ * For example: { "ctrl+c": "COPY_2_CLIPBOARD", "arrow_down": "NAVIGATE_DOWN" }
1501
+ *
1502
+ * @example
1503
+ * // Get all available shortcuts in the table
1504
+ * const shortcuts = tableApi.getShortcutActionMapping();
1505
+ *
1506
+ * // Check if a specific shortcut exists
1507
+ * if (shortcuts["ctrl+c"]) {
1508
+ * console.log("Copy shortcut is available with action:", shortcuts["ctrl+c"]);
1509
+ * }
802
1510
  *
803
- * @return {ShortcutActionIdMapping} The mapping of shortcuts to corresponding action.
1511
+ * // Display available shortcuts in the UI
1512
+ * Object.entries(shortcuts).forEach(([key, actionId]) => {
1513
+ * console.log(`${key}: ${actionId}`);
1514
+ * });
804
1515
  */
805
1516
  getShortcutActionMapping() {
806
1517
  return this.tableScope.shortcutService.getShortcutActionMapping();
@@ -808,7 +1519,35 @@ class ge {
808
1519
  /**
809
1520
  * Copies the selected data from the table to the clipboard.
810
1521
  *
811
- * @return {Promise<string>} - A promise that resolves with the copied data as a string.
1522
+ * This method leverages the copyService to extract and copy the currently selected data
1523
+ * from the table. It works with the current selection state and focus position to determine
1524
+ * what content should be copied.
1525
+ *
1526
+ * The copied data is formatted as tab-separated text that can be pasted into spreadsheet
1527
+ * applications like Excel or text editors while maintaining the tabular structure.
1528
+ *
1529
+ * @example
1530
+ * // Copy the currently selected data to clipboard
1531
+ * tableApi.copyToClipboard().then(content => {
1532
+ * console.log('Copied to clipboard:', content);
1533
+ * });
1534
+ *
1535
+ * // Using with a button click handler
1536
+ * function onCopyButtonClick() {
1537
+ * if (tableApi) {
1538
+ * tableApi.copyToClipboard()
1539
+ * .then(content => {
1540
+ * console.log('Successfully copied data to clipboard');
1541
+ * // Optionally do something with the copied content
1542
+ * })
1543
+ * .catch(error => {
1544
+ * console.error('Failed to copy to clipboard:', error);
1545
+ * });
1546
+ * }
1547
+ * }
1548
+ *
1549
+ * @returns {Promise<string>} A promise that resolves with the copied data as a string.
1550
+ * The string contains the tab-separated representation of the selected table data.
812
1551
  */
813
1552
  copyToClipboard() {
814
1553
  return this.tableScope.copyService.copyToClipboard(
@@ -818,11 +1557,33 @@ class ge {
818
1557
  );
819
1558
  }
820
1559
  /**
821
- * Generates and downloads an Excel file based on the table data.
1560
+ * Downloads the current table data as an Excel file.
1561
+ *
1562
+ * This method extracts all visible data from the table (including header, body, and footer areas),
1563
+ * converts it into a matrix format, and triggers a download of an Excel file containing this data.
1564
+ *
1565
+ * The method works by:
1566
+ * 1. Creating an empty matrix to hold all table data
1567
+ * 2. Iterating through each area of the table (header, body, footer)
1568
+ * 3. For each area, iterating through all rows and columns to extract cell values
1569
+ * 4. Passing the complete data matrix to the Excel service for file generation and download
1570
+ *
1571
+ * @param {string} fileName - The name of the Excel file to be downloaded (default: 'table.xlsx')
1572
+ * @param {string} author - Optional metadata for the Excel file to specify the author (default: '')
1573
+ *
1574
+ * @returns {void} The result of the excelService.downloadExcel method call
822
1575
  *
823
- * @param {string} fileName - The name of the Excel file to be downloaded. Defaults to 'table.xlsx'.
824
- * @param {string} author - The author of the Excel file. If not provided, it will remain empty.
825
- * @return {void} No return value. Initiates a file download of the Excel document.
1576
+ * @example
1577
+ * // Download table data with default filename
1578
+ * tableApi.downloadExcel();
1579
+ *
1580
+ * @example
1581
+ * // Download table data with custom filename and author
1582
+ * tableApi.downloadExcel('sales-report.xlsx', 'John Doe');
1583
+ *
1584
+ * @example
1585
+ * // Download table data with custom filename only
1586
+ * tableApi.downloadExcel('quarterly-data.xlsx');
826
1587
  */
827
1588
  downloadExcel(e = "table.xlsx", t = "") {
828
1589
  const s = [], o = this.tableScope.tableModel.getColumnCount(), i = ["header", "body", "footer"];
@@ -838,18 +1599,66 @@ class ge {
838
1599
  return this.tableScope.excelService.downloadExcel(s, e, t);
839
1600
  }
840
1601
  /**
841
- * Retrieves the current scope of the table.
1602
+ * Returns the TableScope instance associated with this TableApi.
1603
+ *
1604
+ * The TableScope provides access to the core functionality and internal state of the table component,
1605
+ * including rendering, event handling, selection, and other low-level operations.
842
1606
  *
843
- * @returns {TableScope} The current scope of the table.
1607
+ * This method is useful for advanced customization scenarios where you need direct access
1608
+ * to the table's internal structure and behaviors.
1609
+ *
1610
+ * @returns {TableScope} The TableScope instance that controls this table component
1611
+ *
1612
+ * @example
1613
+ * // Access the TableScope to perform a custom operation
1614
+ * const tableApi = new TableApi(myTableScope);
1615
+ * const tableScope = tableApi.getTableScope();
1616
+ *
1617
+ * // Example: Manually trigger a context menu at a specific location
1618
+ * const mouseEvent = new MouseEvent('contextmenu');
1619
+ * const geMouseEvent = tableScope.createGeMouseEvent(mouseEvent);
1620
+ * tableScope.contextmenu(geMouseEvent);
844
1621
  */
845
1622
  getTableScope() {
846
1623
  return this.tableScope;
847
1624
  }
848
1625
  /**
849
- * Retrieves the selection model of the table.
1626
+ * Returns the current selection model for the table.
1627
+ *
1628
+ * The selection model manages cell selection state, including single cells, ranges, rows, and columns.
1629
+ * This method provides access to the selection model instance, allowing operations like:
1630
+ * - Checking if cells are selected
1631
+ * - Getting selection ranges
1632
+ * - Modifying selections
1633
+ * - Adding/removing selection event listeners
1634
+ *
1635
+ * @returns {SelectionModelIf | undefined} The current selection model if available, otherwise undefined.
1636
+ *
1637
+ * @example
1638
+ * // Get the selection model
1639
+ * const selectionModel = tableApi.getSelectionModel();
1640
+ *
1641
+ * // Check if a specific cell is selected
1642
+ * if (selectionModel?.isSelected(3, 2)) {
1643
+ * console.log('Cell at row 3, column 2 is selected');
1644
+ * }
1645
+ *
1646
+ * // Get all selected ranges
1647
+ * const ranges = selectionModel?.getRanges();
1648
+ * console.log('Selected ranges:', ranges);
850
1649
  *
851
- * @return {SelectionModelIf | undefined} The selection model of the table,
852
- * or undefined if no selection model is available.
1650
+ * // Clear all selections
1651
+ * selectionModel?.clear();
1652
+ *
1653
+ * // Toggle selection of a cell
1654
+ * selectionModel?.togglePoint(5, 1);
1655
+ *
1656
+ * // Add a selection change listener
1657
+ * selectionModel?.addEventSelectionChangedListener({
1658
+ * selectionChanged: () => {
1659
+ * console.log('Selection has changed');
1660
+ * }
1661
+ * });
853
1662
  */
854
1663
  getSelectionModel() {
855
1664
  return this.tableScope.selectionModel();
@@ -922,7 +1731,7 @@ class ge {
922
1731
  */
923
1732
  setRows(e) {
924
1733
  const t = this.getBodyModel();
925
- t instanceof F ? t.setRows(e) : console.warn("setRows<T>(rows: T[]) only works with AreaModelObjectArray<T>, but this body area model is ", typeof t, t);
1734
+ t instanceof D ? t.setRows(e) : console.warn("setRows<T>(rows: T[]) only works with AreaModelObjectArray<T>, but this body area model is ", typeof t, t);
926
1735
  }
927
1736
  /**
928
1737
  * Adds new rows to the end of the table body.
@@ -940,7 +1749,7 @@ class ge {
940
1749
  */
941
1750
  addRows(e) {
942
1751
  const t = this.getBodyModel();
943
- if (t instanceof F) {
1752
+ if (t instanceof D) {
944
1753
  const s = t;
945
1754
  let o = s.getAllRows();
946
1755
  s.setRows([...o, ...e]);
@@ -965,7 +1774,7 @@ class ge {
965
1774
  */
966
1775
  addRowsAt(e, t) {
967
1776
  const s = this.getBodyModel();
968
- if (s instanceof F) {
1777
+ if (s instanceof D) {
969
1778
  const o = s;
970
1779
  let i = o.getAllRows();
971
1780
  o.setRows([...i.slice(0, t), ...e, ...i.slice(t)]);
@@ -991,7 +1800,7 @@ class ge {
991
1800
  */
992
1801
  removeRows(e, t = (s, o) => s === o) {
993
1802
  const s = this.getBodyModel();
994
- if (s instanceof F) {
1803
+ if (s instanceof D) {
995
1804
  const o = s, i = o.getAllRows().filter((r) => !e.some((l) => t(r, l)));
996
1805
  o.setRows(i);
997
1806
  } else
@@ -1032,7 +1841,7 @@ class ge {
1032
1841
  */
1033
1842
  findRows(e, t = (s, o) => s === o) {
1034
1843
  const s = this.getBodyModel();
1035
- return s instanceof F ? s.getAllRows().filter((i) => e.some((r) => t(i, r))) : (console.warn("findRows<T>(rows: T[], predicate: (a: T, b: T) => boolean) only works with AreaModelObjectArray<T>, but this body area model is ", typeof s, s), []);
1844
+ return s instanceof D ? s.getAllRows().filter((i) => e.some((r) => t(i, r))) : (console.warn("findRows<T>(rows: T[], predicate: (a: T, b: T) => boolean) only works with AreaModelObjectArray<T>, but this body area model is ", typeof s, s), []);
1036
1845
  }
1037
1846
  /**
1038
1847
  * Searches through the filtered rows of the table to find a row that matches specific criteria.
@@ -1089,7 +1898,7 @@ class ge {
1089
1898
  */
1090
1899
  findRowFromFilteredRowsByAllCriteria(e, t) {
1091
1900
  const s = this.getBodyModel();
1092
- if (s instanceof F)
1901
+ if (s instanceof D)
1093
1902
  return s.getFilteredRows().find((i) => t(e, i));
1094
1903
  console.warn("findRowFromFilteredRowsByAllCriteria(...) only works with AreaModelObjectArray<T>, but this body area model is ", typeof s, s);
1095
1904
  }
@@ -1136,7 +1945,7 @@ class ge {
1136
1945
  */
1137
1946
  findRowFromAllRowsByAllCriteria(e, t) {
1138
1947
  const s = this.getBodyModel();
1139
- if (s instanceof F)
1948
+ if (s instanceof D)
1140
1949
  return s.getAllRows().find((i) => t(e, i));
1141
1950
  console.warn("findRowFromAllRowsByAllCriteria(...) only works with AreaModelObjectArray<T>, but this body area model is ", typeof s, s);
1142
1951
  }
@@ -1161,7 +1970,7 @@ class ge {
1161
1970
  */
1162
1971
  updateRows(e, t = (s, o) => s === o) {
1163
1972
  const s = this.getBodyModel();
1164
- if (s instanceof F) {
1973
+ if (s instanceof D) {
1165
1974
  let i = s.getAllRows();
1166
1975
  for (const r of i)
1167
1976
  for (const l of e)
@@ -1330,6 +2139,184 @@ class ge {
1330
2139
  getFirstVisibleRowIndex() {
1331
2140
  return this.tableScope.getFirstVisibleRowIndex();
1332
2141
  }
2142
+ /**
2143
+ * Retrieves the index of the first fully visible row in the table's viewport.
2144
+ *
2145
+ * A row is considered "fully visible" when it's completely within the visible area of the table.
2146
+ * This differs from the regular "visible" row, which might be partially visible at the edges of the viewport.
2147
+ *
2148
+ * This method is useful for:
2149
+ * - Determining which rows are completely in view for operations that require full visibility
2150
+ * - Implementing pagination or virtualization logic that needs to know complete row visibility
2151
+ * - Supporting keyboard navigation that should skip partially visible rows
2152
+ *
2153
+ * @returns {number} The index of the first fully visible row, or -1 if no rows are fully visible
2154
+ *
2155
+ * @example
2156
+ * // Get the first fully visible row index
2157
+ * const firstFullVisibleRow = tableApi.getFirstFullVisibleRowIndex();
2158
+ *
2159
+ * // Check if a specific row is fully visible
2160
+ * const isRowFullyVisible = (rowIndex) => {
2161
+ * const firstFullVisible = tableApi.getFirstFullVisibleRowIndex();
2162
+ * const lastFullVisible = tableApi.getLastFullVisibleRowIndex();
2163
+ * return rowIndex >= firstFullVisible && rowIndex <= lastFullVisible;
2164
+ * };
2165
+ */
2166
+ getFirstFullVisibleRowIndex() {
2167
+ return this.tableScope.getFirstFullVisibleRowIndex();
2168
+ }
2169
+ /**
2170
+ * Returns the index of the last row that is visible in the table's viewport.
2171
+ *
2172
+ * This method retrieves the last visible row index from the table scope, which keeps
2173
+ * track of which rows are currently visible as the user scrolls through the table.
2174
+ *
2175
+ * This can be useful for:
2176
+ * - Implementing virtualized scrolling optimizations
2177
+ * - Determining if specific rows are currently in view
2178
+ * - Implementing features that need to know the visible range of rows
2179
+ *
2180
+ * @returns {number} The index of the last visible row in the table viewport
2181
+ *
2182
+ * @example
2183
+ * // Check if a specific row is currently visible in the viewport
2184
+ * const lastVisibleIndex = tableApi.getLastVisibleRowIndex();
2185
+ * const firstVisibleIndex = tableApi.getFirstVisibleRowIndex();
2186
+ * const isRowVisible = rowIndex >= firstVisibleIndex && rowIndex <= lastVisibleIndex;
2187
+ *
2188
+ * @example
2189
+ * // Get the range of visible rows
2190
+ * const visibleRowsRange = {
2191
+ * first: tableApi.getFirstVisibleRowIndex(),
2192
+ * last: tableApi.getLastVisibleRowIndex()
2193
+ * };
2194
+ * console.log(`Visible rows: ${visibleRowsRange.first} to ${visibleRowsRange.last}`);
2195
+ */
2196
+ getLastVisibleRowIndex() {
2197
+ return this.tableScope.getLastVisibleRowIndex();
2198
+ }
2199
+ /**
2200
+ * Returns the index of the last fully visible row in the table's viewport.
2201
+ *
2202
+ * This method retrieves the last row that is completely visible within the current
2203
+ * viewport of the table. A row is considered "fully visible" when its entire height
2204
+ * is visible without any portion being cut off by the viewport boundaries.
2205
+ *
2206
+ * The distinction between "visible" and "fully visible" is important when scrolling:
2207
+ * - A row can be partially visible (some portion is in view)
2208
+ * - A row can be fully visible (the entire row is in view)
2209
+ *
2210
+ * @returns {number} The index of the last fully visible row in the table.
2211
+ * If no row is fully visible or the table is empty, the method might return -1.
2212
+ *
2213
+ * @example
2214
+ * ```typescript
2215
+ * // Get the index of the last fully visible row
2216
+ * const lastVisibleRowIndex = tableApi.getLastFullVisibleRowIndex();
2217
+ *
2218
+ * // Use this information to determine if a specific row is fully visible
2219
+ * const isRowFullyVisible = rowIndex <= lastVisibleRowIndex && rowIndex >= tableApi.getFirstFullVisibleRowIndex();
2220
+ *
2221
+ * // Can be used with scrolling operations to ensure certain rows are visible
2222
+ * if (rowIndex > lastVisibleRowIndex) {
2223
+ * tableApi.ensureRowIsVisible(rowIndex);
2224
+ * }
2225
+ * ```
2226
+ */
2227
+ getLastFullVisibleRowIndex() {
2228
+ return this.tableScope.getLastFullVisibleRowIndex();
2229
+ }
2230
+ /**
2231
+ * Checks whether logging is currently active for the table component.
2232
+ *
2233
+ * This method returns the current state of logging for the table. When logging is active,
2234
+ * the table outputs detailed information about its operations to the console, including:
2235
+ *
2236
+ * - Rendering processes and lifecycle events
2237
+ * - Data modifications and updates
2238
+ * - Event handling and user interactions
2239
+ * - Performance metrics and state changes
2240
+ *
2241
+ * Logging can be toggled using the `setLoggingActive(boolean)` method.
2242
+ *
2243
+ * @returns {boolean} True if logging is currently enabled, false otherwise.
2244
+ *
2245
+ * @example
2246
+ * // Check if logging is enabled
2247
+ * if (tableApi.isLoggingActive()) {
2248
+ * console.log("Table logging is currently active");
2249
+ * }
2250
+ *
2251
+ * // Conditionally enable logging only if it's not already active
2252
+ * if (!tableApi.isLoggingActive()) {
2253
+ * tableApi.setLoggingActive(true);
2254
+ *
2255
+ * // Perform operations that need debugging
2256
+ * tableApi.updateCells([
2257
+ * {
2258
+ * area: "body",
2259
+ * rowIndex: 2,
2260
+ * columnIndex: 3,
2261
+ * value: "New Value",
2262
+ * cssClasses: { "highlight": true }
2263
+ * }
2264
+ * ]);
2265
+ *
2266
+ * // Run some additional operations...
2267
+ *
2268
+ * // Disable logging when finished
2269
+ * tableApi.setLoggingActive(false);
2270
+ * }
2271
+ */
2272
+ setLoggingActive(e) {
2273
+ this.tableScope.loggingActive = e;
2274
+ }
2275
+ /**
2276
+ * Checks whether logging is currently active for the table component.
2277
+ *
2278
+ * This method returns the current state of logging for the table. When logging is active,
2279
+ * the table outputs detailed information about its operations to the console, including:
2280
+ *
2281
+ * - Rendering processes and lifecycle events
2282
+ * - Data modifications and updates
2283
+ * - Event handling and user interactions
2284
+ * - Performance metrics and state changes
2285
+ *
2286
+ * Logging can be toggled using the `setLoggingActive(boolean)` method.
2287
+ *
2288
+ * @returns {boolean} True if logging is currently enabled, false otherwise.
2289
+ *
2290
+ * @example
2291
+ * // Check if logging is enabled
2292
+ * if (tableApi.isLoggingActive()) {
2293
+ * console.log("Table logging is currently active");
2294
+ * }
2295
+ *
2296
+ * // Conditionally enable logging only if it's not already active
2297
+ * if (!tableApi.isLoggingActive()) {
2298
+ * tableApi.setLoggingActive(true);
2299
+ *
2300
+ * // Perform operations that need debugging
2301
+ * tableApi.updateCells([
2302
+ * {
2303
+ * area: "body",
2304
+ * rowIndex: 2,
2305
+ * columnIndex: 3,
2306
+ * value: "New Value",
2307
+ * cssClasses: { "highlight": true }
2308
+ * }
2309
+ * ]);
2310
+ *
2311
+ * // Run some additional operations...
2312
+ *
2313
+ * // Disable logging when finished
2314
+ * tableApi.setLoggingActive(false);
2315
+ * }
2316
+ */
2317
+ isLoggingActive() {
2318
+ return this.tableScope.loggingActive;
2319
+ }
1333
2320
  }
1334
2321
  class z {
1335
2322
  constructor(e) {
@@ -1656,7 +2643,7 @@ class Se {
1656
2643
  this.dom.setStyle(this.contentWrapperDiv, "width", e), this.dom.setStyle(this.contentWrapperDiv, "height", t);
1657
2644
  }
1658
2645
  }
1659
- class A {
2646
+ class R {
1660
2647
  /**
1661
2648
  * Represents a constructor for a class.
1662
2649
  * @constructor
@@ -1670,7 +2657,7 @@ class A {
1670
2657
  this.r1 = e, this.c1 = t, this.r2 = s, this.c2 = o, this.gammaRange = i;
1671
2658
  }
1672
2659
  static create(e) {
1673
- return e.gammaRange === void 0 && (e.gammaRange = !1), new A(
2660
+ return e.gammaRange === void 0 && (e.gammaRange = !1), new R(
1674
2661
  e.rowIndex1,
1675
2662
  e.columnIndex1,
1676
2663
  e.rowIndex2,
@@ -1679,13 +2666,13 @@ class A {
1679
2666
  );
1680
2667
  }
1681
2668
  static singleCell(e, t) {
1682
- return new A(e, t, e, t);
2669
+ return new R(e, t, e, t);
1683
2670
  }
1684
2671
  static singleRow(e) {
1685
- return new A(e, 0, e, Number.MAX_SAFE_INTEGER);
2672
+ return new R(e, 0, e, Number.MAX_SAFE_INTEGER);
1686
2673
  }
1687
2674
  static singleColumn(e) {
1688
- return new A(0, e, Number.MAX_SAFE_INTEGER, e);
2675
+ return new R(0, e, Number.MAX_SAFE_INTEGER, e);
1689
2676
  }
1690
2677
  isInRange(e, t) {
1691
2678
  return e >= this.r1 && e <= this.r2 && t >= this.c1 && t <= this.c2;
@@ -1707,7 +2694,7 @@ class ye {
1707
2694
  i === 0 && (i = 1), r === 0 && (r = 1);
1708
2695
  const l = "gammaCells" in this.areaModel;
1709
2696
  this.colAndRowspanRanges.push(
1710
- new A(s, o, s + r - 1, o + i - 1, l)
2697
+ new R(s, o, s + r - 1, o + i - 1, l)
1711
2698
  );
1712
2699
  }
1713
2700
  }
@@ -1732,11 +2719,11 @@ class we {
1732
2719
  class xe extends Se {
1733
2720
  constructor(e, t, s, o) {
1734
2721
  var r, l;
1735
- super(e, t, s, o), this.dragging = !1, this.editing = !1, this.storedColumnWidths = [], this.scrollLeft = 0, this.scrollViewportLeft = 0, this.scrollFactorY = 0, this.scrollFactorX = 0, this.cleanupFunctions = {
2722
+ super(e, t, s, o), this.firstVisibleRowIndex = -1, this.lastVisibleRowIndex = -1, this.firstFullVisibleRowIndex = -1, this.lastFullVisibleRowIndex = -1, this.displayedRowCount = 0, this.pixelLimitForFullVisible = 5, this.loggingActive = !1, this.dragging = !1, this.editing = !1, this.storedColumnWidths = [], this.scrollLeft = 0, this.scrollViewportLeft = 0, this.scrollFactorY = 0, this.scrollFactorX = 0, this.cleanupFunctions = {
1736
2723
  header: [],
1737
2724
  body: [],
1738
2725
  footer: []
1739
- }, this.tree = !1, this.colAndRowspanModels = new we(), this.firstVisibleRowIndex = -1, this.draggingTargetColumnIndex = -1, this.removables = [], this.displayedRowCount = 0, this.tableModel.getSelectionModel ? this.getSelectionModel = this.tableModel.getSelectionModel : (r = this.tableOptions) != null && r.getSelectionModel && (this.getSelectionModel = this.tableOptions.getSelectionModel), (l = this.tableOptions) != null && l.getFocusModel && (this.getFocusModel = this.tableOptions.getFocusModel), V(t.getAreaModel("body")) && (this.tree = !0), ["header", "body", "footer"].forEach(
2726
+ }, this.tree = !1, this.colAndRowspanModels = new we(), this.draggingTargetColumnIndex = -1, this.removables = [], this.tableModel.getSelectionModel ? this.getSelectionModel = this.tableModel.getSelectionModel : (r = this.tableOptions) != null && r.getSelectionModel && (this.getSelectionModel = this.tableOptions.getSelectionModel), (l = this.tableOptions) != null && l.getFocusModel && (this.getFocusModel = this.tableOptions.getFocusModel), $(t.getAreaModel("body")) && (this.tree = !0), ["header", "body", "footer"].forEach(
1740
2727
  (a) => {
1741
2728
  var n;
1742
2729
  this.colAndRowspanModels[a] = new ye(t, t.getAreaModel(a)), (n = this.colAndRowspanModels[a]) == null || n.init();
@@ -1889,12 +2876,27 @@ class xe extends Se {
1889
2876
  }
1890
2877
  const d = r.getCustomClassesAt(t, s);
1891
2878
  d.length && this.dom.addClasses(d, a);
1892
- const u = r.getCustomStyleAt(t, s);
1893
- if (u)
1894
- for (const g in u)
1895
- this.dom.setStyle(a, g, u[g]);
2879
+ const m = r.getCustomStyleAt(t, s);
2880
+ if (m)
2881
+ for (const g in m)
2882
+ this.dom.setStyle(a, g, m[g]);
1896
2883
  }
1897
2884
  }
2885
+ getFirstVisibleRowIndex() {
2886
+ return this.firstVisibleRowIndex;
2887
+ }
2888
+ getLastVisibleRowIndex() {
2889
+ return this.lastVisibleRowIndex;
2890
+ }
2891
+ getFirstFullVisibleRowIndex() {
2892
+ return this.firstFullVisibleRowIndex;
2893
+ }
2894
+ getLastFullVisibleRowIndex() {
2895
+ return this.lastFullVisibleRowIndex;
2896
+ }
2897
+ getDisplayedRowCount() {
2898
+ return this.displayedRowCount;
2899
+ }
1898
2900
  /**
1899
2901
  * Stores the widths of all columns in the table.
1900
2902
  *
@@ -1995,16 +2997,17 @@ class xe extends Se {
1995
2997
  s.child.innerText = "", o.child.innerText = "", i.child.innerText = "";
1996
2998
  const l = 0, a = this.areaBodyCenterGeo.width, n = this.tableModel.getPadding(), c = this.tableModel.getAreaModel(e), h = c.getRowCount();
1997
2999
  for (; this.cleanupFunctions[e].length; ) {
1998
- const m = this.cleanupFunctions[e].shift();
1999
- m && m();
3000
+ const u = this.cleanupFunctions[e].shift();
3001
+ u && u();
2000
3002
  }
2001
3003
  let d = t;
2002
- const u = this.tableModel.getColumnCount(), g = this.tableModel.getFixedRightColumnCount(), b = this.tableModel.getFixedLeftColumnCount();
2003
- for (let m = 0; m < h; m++) {
2004
- const w = d, S = m === h - 1, v = this.tableModel.getRowHeight(e, m);
3004
+ const m = this.tableModel.getColumnCount(), g = this.tableModel.getFixedRightColumnCount(), b = this.tableModel.getFixedLeftColumnCount();
3005
+ e === "body" && (this.firstVisibleRowIndex = -1, this.firstFullVisibleRowIndex = -1, this.lastVisibleRowIndex = -1, this.lastFullVisibleRowIndex = -1);
3006
+ for (let u = 0; u < h; u++) {
3007
+ const w = d, S = u === h - 1, v = this.tableModel.getRowHeight(e, u);
2005
3008
  if (w + v > 0) {
2006
- this.firstVisibleRowIndex = m;
2007
- let x = { left: l, width: a, height: v, top: w, index: m }, y = this.dom.addRowDiv(o, x, m, e, "center");
3009
+ e === "body" && this.firstVisibleRowIndex === -1 && (this.firstVisibleRowIndex = u, this.firstFullVisibleRowIndex = w < -this.pixelLimitForFullVisible ? this.firstVisibleRowIndex + 1 : this.firstVisibleRowIndex);
3010
+ let x = { left: l, width: a, height: v, top: w, index: u }, y = this.dom.addRowDiv(o, x, u, e, "center");
2008
3011
  const M = b;
2009
3012
  if (this.adjustColumnsToRowParent({
2010
3013
  areaIdent: e,
@@ -2012,61 +3015,64 @@ class xe extends Se {
2012
3015
  areaModel: c,
2013
3016
  geo: x,
2014
3017
  parent: y,
2015
- rowIndex: m,
3018
+ rowIndex: u,
2016
3019
  columnIndexStart: M,
2017
- columnIndexEnd: u - g - 1,
3020
+ columnIndexEnd: m - g - 1,
2018
3021
  verticalFixed: !1,
2019
3022
  lastRowOfModel: S
2020
- }), n.left > 0 && (x = { left: l, width: this.areaBodyWestGeo.width, height: v, top: w, index: m }, y = this.dom.addRowDiv(s, x, m, e, "west"), this.adjustColumnsToRowParent({
3023
+ }), n.left > 0 && (x = { left: l, width: this.areaBodyWestGeo.width, height: v, top: w, index: u }, y = this.dom.addRowDiv(s, x, u, e, "west"), this.adjustColumnsToRowParent({
2021
3024
  areaIdent: e,
2022
3025
  sideIdent: "west",
2023
3026
  areaModel: c,
2024
3027
  geo: x,
2025
3028
  parent: y,
2026
- rowIndex: m,
3029
+ rowIndex: u,
2027
3030
  columnIndexStart: 0,
2028
3031
  columnIndexEnd: M - 1,
2029
3032
  verticalFixed: !0,
2030
3033
  lastRowOfModel: S
2031
- })), n.right > 0 && (x = { left: l, width: this.areaBodyEastGeo.width, height: v, top: w, index: m }, y = this.dom.addRowDiv(i, x, m, e, "east"), this.adjustColumnsToRowParent({
3034
+ })), n.right > 0 && (x = { left: l, width: this.areaBodyEastGeo.width, height: v, top: w, index: u }, y = this.dom.addRowDiv(i, x, u, e, "east"), this.adjustColumnsToRowParent({
2032
3035
  areaIdent: e,
2033
3036
  sideIdent: "east",
2034
3037
  areaModel: c,
2035
3038
  geo: x,
2036
3039
  parent: y,
2037
- rowIndex: m,
2038
- columnIndexStart: u - g,
2039
- columnIndexEnd: u - 1,
3040
+ rowIndex: u,
3041
+ columnIndexStart: m - g,
3042
+ columnIndexEnd: m - 1,
2040
3043
  verticalFixed: !0,
2041
3044
  lastRowOfModel: S
2042
- })), e === "header" && this.tree && m === h - 1) {
2043
- const E = this.dom.applyStyle(
3045
+ })), e === "header" && this.tree && u === h - 1) {
3046
+ const A = this.dom.applyStyle(
2044
3047
  this.dom.setAttribute(
2045
3048
  this.dom.addDiv(y, new T(16, 20, 20, 8)),
2046
3049
  "data-ge-action",
2047
3050
  "toggleExpandCollapseAll"
2048
3051
  ),
2049
3052
  { cursor: "pointer" }
2050
- ), R = this.tableOptions.treeOptions.arrowExpandCollapseAll;
2051
- if (R) {
2052
- const L = this.dom.domService.createText(R.content);
2053
- this.dom.domService.appendChild(E, L), R.style && this.dom.applyStyleString(E, R.style);
3053
+ ), E = this.tableOptions.treeOptions.arrowExpandCollapseAll;
3054
+ if (E) {
3055
+ const O = this.dom.domService.createText(E.content);
3056
+ this.dom.domService.appendChild(A, O), E.style && this.dom.applyStyleString(A, E.style);
2054
3057
  }
2055
3058
  }
2056
3059
  }
2057
3060
  if (d = d + v, d > r) {
2058
- e === "body" && (this.displayedRowCount = this.firstVisibleRowIndex - m);
3061
+ e === "body" && (this.lastVisibleRowIndex = u, this.lastFullVisibleRowIndex = r - d < -this.pixelLimitForFullVisible ? u - 1 : u, this.displayedRowCount = this.lastFullVisibleRowIndex - this.firstFullVisibleRowIndex + 1);
2059
3062
  break;
2060
3063
  }
2061
3064
  }
2062
- if (this.colAndRowspanModels && this.colAndRowspanModels[e]) {
2063
- const m = ((f = this.colAndRowspanModels[e]) == null ? void 0 : f.getRanges()) ?? [];
2064
- if (m.length)
2065
- for (const w of m) {
3065
+ if (this.loggingActive && e === "body" && console.log("render scope: this.firstVisibleRowIndex <- " + this.firstVisibleRowIndex + `
3066
+ render scope: this.firstFullVisibleRowIndex <- ` + this.firstFullVisibleRowIndex + `
3067
+ render scope: this.lastVisibleRowIndex <- ` + this.lastVisibleRowIndex + `
3068
+ render scope: this.lastFullVisibleRowIndex <- ` + this.lastFullVisibleRowIndex), this.colAndRowspanModels && this.colAndRowspanModels[e]) {
3069
+ const u = ((f = this.colAndRowspanModels[e]) == null ? void 0 : f.getRanges()) ?? [];
3070
+ if (u.length)
3071
+ for (const w of u) {
2066
3072
  let S = 0, v = o.child, x = "center";
2067
3073
  if (w.c1 < b)
2068
3074
  v = s.child, x = "west";
2069
- else if (g > 0 && w.c1 >= u - g)
3075
+ else if (g > 0 && w.c1 >= m - g)
2070
3076
  v = i.child, x = "east";
2071
3077
  else {
2072
3078
  const y = this.areaBodyCenterGeo.width - this.tableModel.getContentWidthInPixel();
@@ -2087,10 +3093,10 @@ class xe extends Se {
2087
3093
  * @protected
2088
3094
  */
2089
3095
  drawBigCell(e, t, s, o, i, r) {
2090
- const l = s + this.getRowHeights(0, e.r1 - 1, o).reduce((f, m) => f + m, 0), a = this.tableModel.getColumnCount(), n = this.tableModel.getFixedRightColumnCount();
3096
+ const l = s + this.getRowHeights(0, e.r1 - 1, o).reduce((f, u) => f + u, 0), a = this.tableModel.getColumnCount(), n = this.tableModel.getFixedRightColumnCount();
2091
3097
  let c = 0;
2092
3098
  n > 0 && e.c1 >= a - n && (c = a - n);
2093
- const h = t + this.getColumnWidths(c, e.c1 - 1).reduce((f, m) => f + m, 0), d = this.getRowHeights(e.r1, e.r2, o).reduce((f, m) => f + m, 0), u = this.getColumnWidths(e.c1, e.c2).reduce((f, m) => f + m, 0);
3099
+ const h = t + this.getColumnWidths(c, e.c1 - 1).reduce((f, u) => f + u, 0), d = this.getRowHeights(e.r1, e.r2, o).reduce((f, u) => f + u, 0), m = this.getColumnWidths(e.c1, e.c2).reduce((f, u) => f + u, 0);
2094
3100
  let g = !1;
2095
3101
  const b = this.getSelectionModel ? this.getSelectionModel() : void 0;
2096
3102
  b && (g = b.getSelectionCount(e.r1, e.c1) > 0), e.gammaRange ? this.renderCell({
@@ -2101,7 +3107,7 @@ class xe extends Se {
2101
3107
  columnIndex: e.c1,
2102
3108
  left: h,
2103
3109
  top: l,
2104
- width: u,
3110
+ width: m,
2105
3111
  height: d,
2106
3112
  parent: i,
2107
3113
  cellSelected: g,
@@ -2115,7 +3121,7 @@ class xe extends Se {
2115
3121
  columnIndex: e.c1,
2116
3122
  left: h,
2117
3123
  top: l,
2118
- width: u,
3124
+ width: m,
2119
3125
  height: d,
2120
3126
  parent: i,
2121
3127
  cellSelected: g,
@@ -2126,7 +3132,7 @@ class xe extends Se {
2126
3132
  columnIndex: e.c1,
2127
3133
  cellLeft: h,
2128
3134
  cellTop: l,
2129
- cellWidth: u,
3135
+ cellWidth: m,
2130
3136
  cellHeight: d,
2131
3137
  parent: i
2132
3138
  });
@@ -2177,41 +3183,41 @@ class xe extends Se {
2177
3183
  const f = this.areaBodyCenterGeo.width - this.tableModel.getContentWidthInPixel();
2178
3184
  h = this.scrollFactorX * f;
2179
3185
  }
2180
- const d = 0, u = !!(e === "body" && t);
3186
+ const d = 0, m = !!(e === "body" && t);
2181
3187
  let g = h;
2182
3188
  for (let f = l; f <= a; f++) {
2183
- const m = g, w = this.tableModel.getColumnWidth(f);
2184
- if (w > 0 && m + w > 0) {
3189
+ const u = g, w = this.tableModel.getColumnWidth(f);
3190
+ if (w > 0 && u + w > 0) {
2185
3191
  let S = o.height;
2186
3192
  const v = s.getRowspanAt(r, f), x = s.getColspanAt(r, f);
2187
- v > 1 && (S = this.getRowHeights(r, r + v - 1, s).reduce((E, R) => E + R, 0));
3193
+ v > 1 && (S = this.getRowHeights(r, r + v - 1, s).reduce((A, E) => A + E, 0));
2188
3194
  let y = w;
2189
- x > 1 && (y = this.getColumnWidths(f, f + x - 1).reduce((E, R) => E + R, 0));
3195
+ x > 1 && (y = this.getColumnWidths(f, f + x - 1).reduce((A, E) => A + E, 0));
2190
3196
  let M = !1;
2191
3197
  if (this.colAndRowspanModels && this.colAndRowspanModels[e] && (b = this.colAndRowspanModels[e]) != null && b.isInRange(r, f) && (M = !0), this.draggingTargetColumnIndex === f && e !== "header") {
2192
- this.renderDragTargetDiv(i, m, d, y, S);
2193
- const E = { left: m, top: d, width: y, height: S };
2194
- this.dom.addColumnBorderDivs(this.tableOptions, i, E, e, t);
3198
+ this.renderDragTargetDiv(i, u, d, y, S);
3199
+ const A = { left: u, top: d, width: y, height: S };
3200
+ this.dom.addColumnBorderDivs(this.tableOptions, i, A, e, t);
2195
3201
  } else {
2196
- const E = this.renderSelectedBackgroundDiv(M, u, t, s, r, f, i, m, d, y, S);
3202
+ const A = this.renderSelectedBackgroundDiv(M, m, t, s, r, f, i, u, d, y, S);
2197
3203
  "gammaCells" in s && s.getValueAt(r, f) && (M = !1), M || this.renderCell({
2198
3204
  areaModel: s,
2199
3205
  areaIdent: e,
2200
3206
  sideIdent: t,
2201
3207
  rowIndex: r,
2202
3208
  columnIndex: f,
2203
- left: m,
3209
+ left: u,
2204
3210
  top: d,
2205
3211
  width: y,
2206
3212
  height: S,
2207
3213
  parent: i,
2208
- cellSelected: E,
3214
+ cellSelected: A,
2209
3215
  lastRowOfModel: c,
2210
3216
  gammaRange: !0
2211
3217
  }), e === "header" && this.tableOptions.columnsResizable && this.renderHeaderCellResizeHandle({
2212
3218
  rowIndex: r,
2213
3219
  columnIndex: f,
2214
- cellLeft: m,
3220
+ cellLeft: u,
2215
3221
  cellTop: d,
2216
3222
  cellWidth: y,
2217
3223
  cellHeight: S,
@@ -2250,7 +3256,7 @@ class xe extends Se {
2250
3256
  lastRowOfModel: h
2251
3257
  }) {
2252
3258
  var j;
2253
- const u = this.editorRenderer && this.editorRendererRow === o && this.editorRendererColumn === i ? this.editorRenderer : e.getCellRenderer(o, i), g = { left: r, width: l, height: a, top: n, index: i }, b = e.getRowByIndex(o);
3259
+ const m = this.editorRenderer && this.editorRendererRow === o && this.editorRendererColumn === i ? this.editorRenderer : e.getCellRenderer(o, i), g = { left: r, width: l, height: a, top: n, index: i }, b = e.getRowByIndex(o);
2254
3260
  let f = "none";
2255
3261
  if (i === this.getTreeArrowColumnIndex() && B(b)) {
2256
3262
  const C = b;
@@ -2261,7 +3267,7 @@ class xe extends Se {
2261
3267
  const C = this.tableModel.getColumnDef(i);
2262
3268
  (!(C != null && C.sortIconVisible) || C != null && C.sortIconVisible()) && (w = C == null ? void 0 : C.sortState);
2263
3269
  }
2264
- const S = e.getValueAt(o, i), v = u ? "" : `${S}`, x = e.isRowChecked(o), y = this.dom.addColumnDiv(
3270
+ const S = e.getValueAt(o, i), v = m ? "" : `${S}`, x = e.isRowChecked(o), y = this.dom.addColumnDiv(
2265
3271
  {
2266
3272
  parent: c,
2267
3273
  geo: g,
@@ -2277,21 +3283,21 @@ class xe extends Se {
2277
3283
  }
2278
3284
  ), M = e.getTooltipAt(o, i);
2279
3285
  M && this.dom.setAttribute(y, "title", M);
2280
- const E = this.tableModel.getColumnDef(i);
2281
- E && E.classes[t] && this.dom.addClasses(E.classes[t], y);
2282
- let R;
2283
- u && (R = u.render(y, o, i, t, e, S, this.dom.domService));
2284
- const L = e.getCustomClassesAt(o, i);
2285
- if (L.length && this.dom.addClasses(L, y), this.dom.addColumnBorderDivs(this.tableOptions, c, g, t, s), h && this.dom.addHorizontalBorder({ left: r, width: l, height: a, top: n + a }, c), this.getFocusModel && t === "body") {
3286
+ const A = this.tableModel.getColumnDef(i);
3287
+ A && A.classes[t] && this.dom.addClasses(A.classes[t], y);
3288
+ let E;
3289
+ m && (E = m.render(y, o, i, t, e, S, this.dom.domService));
3290
+ const O = e.getCustomClassesAt(o, i);
3291
+ if (O.length && this.dom.addClasses(O, y), this.dom.addColumnBorderDivs(this.tableOptions, c, g, t, s), h && this.dom.addHorizontalBorder({ left: r, width: l, height: a, top: n + a }, c), this.getFocusModel && t === "body") {
2286
3292
  const C = this.getFocusModel();
2287
3293
  C != null && C.hasFocus(o, i) && this.dom.addFocusBorderDivs(c, g, {});
2288
3294
  }
2289
3295
  t === "header" && this.dom.setAttribute(y, "data-ge-action", "drag-column");
2290
- const $ = e.getCustomStyleAt(o, i);
2291
- if ($)
2292
- for (const C in $)
2293
- this.dom.setStyle(y, C, $[C]);
2294
- return [y, R];
3296
+ const H = e.getCustomStyleAt(o, i);
3297
+ if (H)
3298
+ for (const C in H)
3299
+ this.dom.setStyle(y, C, H[C]);
3300
+ return [y, E];
2295
3301
  }
2296
3302
  /**
2297
3303
  * Applies CSS classes to an HTML element.
@@ -2457,7 +3463,7 @@ class xe extends Se {
2457
3463
  if (r) {
2458
3464
  const l = e.index ?? 0, a = this.draggingColumn;
2459
3465
  for (let n = 0; n < r; n++) {
2460
- const c = s, h = i.getRowHeight(n), d = { left: 0, width: e.width, height: h, top: c, index: n }, u = i.getValueAt(n, l), g = i.getCellRenderer(n, l), b = g ? "" : `${u}`, f = {
3466
+ const c = s, h = i.getRowHeight(n), d = { left: 0, width: e.width, height: h, top: c, index: n }, m = i.getValueAt(n, l), g = i.getCellRenderer(n, l), b = g ? "" : `${m}`, f = {
2461
3467
  parent: a,
2462
3468
  geo: d,
2463
3469
  rowIndex: n,
@@ -2465,17 +3471,17 @@ class xe extends Se {
2465
3471
  areaIdent: t,
2466
3472
  sideIdent: o,
2467
3473
  text: b
2468
- }, m = this.dom.addColumnDiv(f);
3474
+ }, u = this.dom.addColumnDiv(f);
2469
3475
  let w;
2470
- g && (w = g.render(m, n, l, t, i, u, this.dom.domService), w && this.cleanupFunctions[t].push(w));
3476
+ g && (w = g.render(u, n, l, t, i, m, this.dom.domService), w && this.cleanupFunctions[t].push(w));
2471
3477
  const S = i.getCustomClassesAt(n, l);
2472
- S.length && this.dom.addClasses(S, m);
3478
+ S.length && this.dom.addClasses(S, u);
2473
3479
  const v = this.tableModel.getColumnDef(l);
2474
- v && v.classes[t] && this.dom.addClasses(v.classes[t], m), this.dom.addColumnBorderDivs(this.tableOptions, a, d, t, o);
3480
+ v && v.classes[t] && this.dom.addClasses(v.classes[t], u), this.dom.addColumnBorderDivs(this.tableOptions, a, d, t, o);
2475
3481
  const x = i.getCustomStyleAt(n, l);
2476
3482
  if (x)
2477
3483
  for (const y in x)
2478
- this.dom.setStyle(m, y, x[y]);
3484
+ this.dom.setStyle(u, y, x[y]);
2479
3485
  s = s + h;
2480
3486
  }
2481
3487
  }
@@ -2528,9 +3534,9 @@ class xe extends Se {
2528
3534
  renderSelectedBackgroundDiv(e, t, s, o, i, r, l, a, n, c, h) {
2529
3535
  let d = !1;
2530
3536
  if (!e && t && o.isSelectable(i, r) && this.getSelectionModel) {
2531
- const u = this.getSelectionModel();
2532
- if (u) {
2533
- const g = u.getSelectionCount(i, r);
3537
+ const m = this.getSelectionModel();
3538
+ if (m) {
3539
+ const g = m.getSelectionCount(i, r);
2534
3540
  d = g > 0;
2535
3541
  for (let b = 0; b < g; b++) {
2536
3542
  const f = this.dom.applyStylePosistionAbsolute(
@@ -2576,7 +3582,7 @@ class xe extends Se {
2576
3582
  cellSelected: h,
2577
3583
  lastRowOfModel: d
2578
3584
  }) {
2579
- const [u, g] = this.addAndRenderCellDiv({
3585
+ const [m, g] = this.addAndRenderCellDiv({
2580
3586
  areaModel: e,
2581
3587
  areaIdent: t,
2582
3588
  sideIdent: s,
@@ -2589,7 +3595,7 @@ class xe extends Se {
2589
3595
  parent: c,
2590
3596
  lastRowOfModel: d
2591
3597
  });
2592
- h && this.dom.addClass(`ge-table-${t}-${s}-selected-range`, u), g && this.cleanupFunctions[t].push(g);
3598
+ h && this.dom.addClass(`ge-table-${t}-${s}-selected-range`, m), g && this.cleanupFunctions[t].push(g);
2593
3599
  }
2594
3600
  /**
2595
3601
  * Render the header cell resize handle.
@@ -2637,7 +3643,7 @@ class ve {
2637
3643
  }
2638
3644
  }
2639
3645
  }
2640
- class Ae {
3646
+ class Re {
2641
3647
  constructor(e = -1, t = -1) {
2642
3648
  this.rowIndex = e, this.columnIndex = t;
2643
3649
  }
@@ -2647,10 +3653,10 @@ class G {
2647
3653
  this.cells = e;
2648
3654
  }
2649
3655
  static createSingle(e, t) {
2650
- return new G([new Ae(e, t)]);
3656
+ return new G([new Re(e, t)]);
2651
3657
  }
2652
3658
  }
2653
- class Ee {
3659
+ class Ae {
2654
3660
  constructor(e) {
2655
3661
  var t, s;
2656
3662
  this.tableScope = e, (t = this.tableScope.tableOptions) != null && t.getSelectionModel && (this.getSelectionModel = this.tableScope.tableOptions.getSelectionModel), (s = this.tableScope.tableOptions) != null && s.getFocusModel && (this.getFocusModel = this.tableScope.tableOptions.getFocusModel);
@@ -2659,8 +3665,8 @@ class Ee {
2659
3665
  var i, r, l, a, n, c, h;
2660
3666
  let s = !1, o = !1;
2661
3667
  if (this.getSelectionModel && this.getFocusModel) {
2662
- const d = this.getSelectionModel(), u = this.getFocusModel();
2663
- d && u && (u.hasFocus(e.rowIndex, e.columnIndex) || (u.setFocus(e.rowIndex, e.columnIndex), this.tableScope.onFocusChanged(u), s = !0), (i = e.originalEvent) != null && i.shiftKey || d.hasSelection() && (d.clear(), s = !0), (r = e.originalEvent) != null && r.shiftKey && this.previousEvt ? (d.addSelection(this.createRangeByEvents(e, this.previousEvt)), o = !0, s = !0) : (l = e.originalEvent) != null && l.altKey && ((a = e.originalEvent) != null && a.ctrlKey || (n = e.originalEvent) != null && n.metaKey) ? (d.removeSelection(A.singleCell(e.rowIndex, e.columnIndex)), o = !0, s = !0) : (c = e.originalEvent) != null && c.ctrlKey || (h = e.originalEvent) != null && h.metaKey ? (d.addSelection(A.singleCell(e.rowIndex, e.columnIndex)), o = !0, s = !0) : (d.firstClick(e.rowIndex, e.columnIndex), s = !0), this.tableScope.onSelectionChanged(d));
3668
+ const d = this.getSelectionModel(), m = this.getFocusModel();
3669
+ d && m && (m.hasFocus(e.rowIndex, e.columnIndex) || (m.setFocus(e.rowIndex, e.columnIndex), this.tableScope.onFocusChanged(m), s = !0), (i = e.originalEvent) != null && i.shiftKey || d.hasSelection() && (d.clear(), s = !0), (r = e.originalEvent) != null && r.shiftKey && this.previousEvt ? (d.addSelection(this.createRangeByEvents(e, this.previousEvt)), o = !0, s = !0) : (l = e.originalEvent) != null && l.altKey && ((a = e.originalEvent) != null && a.ctrlKey || (n = e.originalEvent) != null && n.metaKey) ? (d.removeSelection(R.singleCell(e.rowIndex, e.columnIndex)), o = !0, s = !0) : (c = e.originalEvent) != null && c.ctrlKey || (h = e.originalEvent) != null && h.metaKey ? (d.addSelection(R.singleCell(e.rowIndex, e.columnIndex)), o = !0, s = !0) : (d.firstClick(e.rowIndex, e.columnIndex), s = !0), this.tableScope.onSelectionChanged(d));
2664
3670
  }
2665
3671
  return o ? this.previousEvt = void 0 : this.previousEvt = e == null ? void 0 : e.clone(), s;
2666
3672
  }
@@ -2683,7 +3689,7 @@ class Ee {
2683
3689
  createRangeByEvents(e, t) {
2684
3690
  t || (t = e);
2685
3691
  const s = Math.min(e.rowIndex, t == null ? void 0 : t.rowIndex), o = Math.max(e.rowIndex, t == null ? void 0 : t.rowIndex), i = Math.min(e.columnIndex, t == null ? void 0 : t.columnIndex), r = Math.max(e.columnIndex, t == null ? void 0 : t.columnIndex);
2686
- return A.create({
3692
+ return R.create({
2687
3693
  rowIndex1: s,
2688
3694
  columnIndex1: i,
2689
3695
  rowIndex2: o,
@@ -2691,7 +3697,7 @@ class Ee {
2691
3697
  });
2692
3698
  }
2693
3699
  }
2694
- class Re {
3700
+ class Ee {
2695
3701
  get() {
2696
3702
  return {
2697
3703
  f2: "START_EDITING",
@@ -2749,7 +3755,7 @@ function X(p) {
2749
3755
  let t = "";
2750
3756
  return p.ctrlKey && (t += " ctrl"), p.altKey && (t += t + " alt"), p.shiftKey && (t += t + " shift"), p.metaKey && (t += t + " cmd"), Te(t + " " + e);
2751
3757
  }
2752
- class De {
3758
+ class Fe {
2753
3759
  constructor(e) {
2754
3760
  this.tableScope = e, this.shortcutActionIdMapping = {}, this.listener = [], this.listener.push(e), this.init();
2755
3761
  }
@@ -2771,7 +3777,7 @@ class De {
2771
3777
  (t = (e = this.tableScope) == null ? void 0 : e.tableOptions) != null && t.shortcutActionsDisabled ? this.isDebug() && console.debug("ShortcutService skipped.") : (this.assignPredefinedSystemShortcutMappings(), Object.assign(this.shortcutActionIdMapping, this.tableScope.tableOptions.shortcutActionIdMapping), this.isDebug() && console.debug("ShortcutService", this.shortcutActionIdMapping), this.tableScope.hostElement.addEventListener("keydown", this.onKeyDown.bind(this)));
2772
3778
  }
2773
3779
  assignPredefinedSystemShortcutMappings() {
2774
- this.isMacintosh() ? Object.assign(this.shortcutActionIdMapping, new Me().get()) : Object.assign(this.shortcutActionIdMapping, new Re().get());
3780
+ this.isMacintosh() ? Object.assign(this.shortcutActionIdMapping, new Me().get()) : Object.assign(this.shortcutActionIdMapping, new Ee().get());
2775
3781
  }
2776
3782
  isMacintosh() {
2777
3783
  return navigator.platform.indexOf("Mac") > -1;
@@ -2891,7 +3897,7 @@ class ee {
2891
3897
  e.setAttribute(t, s);
2892
3898
  }
2893
3899
  }
2894
- class Fe {
3900
+ class De {
2895
3901
  render(e, t, s, o, i, r, l) {
2896
3902
  if (i.isEditable(t, s)) {
2897
3903
  l.addClass(e, "ge-table-row-input-div");
@@ -2912,7 +3918,7 @@ class Fe {
2912
3918
  }
2913
3919
  }
2914
3920
  }
2915
- class ke {
3921
+ class Ie {
2916
3922
  constructor(e = "none", t = "single") {
2917
3923
  this.selectionType = e, this.selectionMode = t, this.ranges = [], this.negativeRanges = [], this.allSelected = !1, this.silent = !1, this.listenerArr = [];
2918
3924
  }
@@ -2931,7 +3937,7 @@ class ke {
2931
3937
  this.silent || this.listenerArr.forEach((e) => e.onSelectionChanged(this));
2932
3938
  }
2933
3939
  firstClick(e, t) {
2934
- this.selectionType === "row" ? this.addRange(A.singleRow(e)) : this.selectionType === "column" && this.addRange(A.singleColumn(t));
3940
+ this.selectionType === "row" ? this.addRange(R.singleRow(e)) : this.selectionType === "column" && this.addRange(R.singleColumn(t));
2935
3941
  }
2936
3942
  getSelectionCount(e, t) {
2937
3943
  let s = 0;
@@ -2982,10 +3988,10 @@ class ke {
2982
3988
  if (this.selectionType === "none")
2983
3989
  return;
2984
3990
  let t = e;
2985
- this.selectionType === "row" ? t = A.singleRow(e.r1) : this.selectionType === "column" && (t = A.singleColumn(e.c1)), this.negativeRanges.push(t), this.fireChangeEvent();
3991
+ this.selectionType === "row" ? t = R.singleRow(e.r1) : this.selectionType === "column" && (t = R.singleColumn(e.c1)), this.negativeRanges.push(t), this.fireChangeEvent();
2986
3992
  }
2987
3993
  togglePoint(e, t) {
2988
- this.getSelectionCount(e, t) > 0 ? this.removeSelection(A.singleCell(e, t)) : this.addSelection(A.singleCell(e, t));
3994
+ this.getSelectionCount(e, t) > 0 ? this.removeSelection(R.singleCell(e, t)) : this.addSelection(R.singleCell(e, t));
2989
3995
  }
2990
3996
  isSelected(e, t) {
2991
3997
  return this.getSelectionCount(e, t) > 0;
@@ -2994,7 +4000,7 @@ class ke {
2994
4000
  this.selectionType !== "none" && (this.allSelected = !1, this.selectionMode === "single" && (this.ranges = []), this.selectionType === "row" ? (e.c1 = 0, e.c2 = Number.MAX_SAFE_INTEGER) : this.selectionType === "column" ? (e.r1 = 0, e.r2 = Number.MAX_SAFE_INTEGER) : this.selectionType === "cell" ? (e.r2 = e.r1, e.c2 = e.c1) : this.selectionType, this.ranges.push(e), this.fireChangeEvent());
2995
4001
  }
2996
4002
  }
2997
- class Ie {
4003
+ class ke {
2998
4004
  constructor(e = "none") {
2999
4005
  this.selectionType = e, this.rowIndex = -1, this.columnIndex = -1, this.changed = !1, this.listenerArr = [];
3000
4006
  }
@@ -3032,11 +4038,11 @@ class Ie {
3032
4038
  }
3033
4039
  }
3034
4040
  class te {
3035
- constructor(e = new D(
4041
+ constructor(e = new F(
3036
4042
  "❯",
3037
4043
  "",
3038
4044
  ["gt-table-icon-expanded"]
3039
- ), t = new D(
4045
+ ), t = new F(
3040
4046
  "❯",
3041
4047
  "transform: rotate(180deg) translate(-100%, -100%); transform-origin: 0 0;",
3042
4048
  ["ge-table-icon-collapsed"]
@@ -3045,17 +4051,17 @@ class te {
3045
4051
  }
3046
4052
  // `⊖ `, `⊕ `;
3047
4053
  }
3048
- const Oe = new ke(), Le = new Ie("cell");
4054
+ const Le = new Ie(), Oe = new ke("cell");
3049
4055
  class se {
3050
4056
  constructor() {
3051
4057
  this.overflowX = "auto", this.overflowY = "auto", this.horizontalBorderVisible = !0, this.verticalBorderVisible = !0, this.footerSeparatorBorderVisible = !0, this.headerSeparatorBorderVisible = !0, this.fixedEastSeparatorBorderVisible = !0, this.fixedWestSeparatorBorderVisible = !0, this.tableTopBorderVisible = !0, this.tableBottomBorderVisible = !0, this.hoverRowVisible = !0, this.hoverColumnVisible = !0, this.columnsResizable = !0, this.columnsDraggable = !0, this.columnResizeHandleWidthInPx = 4, this.defaultRowHeights = {
3052
4058
  header: 34,
3053
4059
  body: 34,
3054
4060
  footer: 34
3055
- }, this.footerVerticalSeparator = !1, this.headerToggleExpandCollapseIcons = !1, this.headerVerticalSeparator = !1, this.treeOptions = new Z(), this.headerGroupOptions = new te(), this.showCheckboxWihoutExtraColumn = !1, this.externalFilterFunction = void 0, this.sortedOptions = new Q(), this.sortOrder = ["asc", "desc"], this.shortcutActionsDisabled = !1, this.resizeEventDebounceDelay = 500, this.getEditRenderer = (e, t) => new Fe(), this.getSelectionModel = () => Oe, this.getFocusModel = () => Le;
4061
+ }, this.footerVerticalSeparator = !1, this.headerToggleExpandCollapseIcons = !1, this.headerVerticalSeparator = !1, this.treeOptions = new Z(), this.headerGroupOptions = new te(), this.showCheckboxWihoutExtraColumn = !1, this.externalFilterFunction = void 0, this.sortedOptions = new Q(), this.sortOrder = ["asc", "desc"], this.shortcutActionsDisabled = !1, this.resizeEventDebounceDelay = 500, this.getEditRenderer = (e, t) => new De(), this.getSelectionModel = () => Le, this.getFocusModel = () => Oe;
3056
4062
  }
3057
4063
  }
3058
- const O = class O {
4064
+ const L = class L {
3059
4065
  /**
3060
4066
  * Returns the content to be copied based on the provided table model, selection model, and focus model.
3061
4067
  *
@@ -3078,9 +4084,9 @@ const O = class O {
3078
4084
  const h = t.isSelected(a, c) ? e.getBodyModel().getTextValueAt(a, c) : "";
3079
4085
  n.push(h);
3080
4086
  }
3081
- l.push(n.join(O.columnSeparatorChar));
4087
+ l.push(n.join(L.columnSeparatorChar));
3082
4088
  }
3083
- return o(l.join(O.rowSeparatorChar));
4089
+ return o(l.join(L.rowSeparatorChar));
3084
4090
  }
3085
4091
  }
3086
4092
  if (s) {
@@ -3133,13 +4139,13 @@ const O = class O {
3133
4139
  mergeRanges(e) {
3134
4140
  let t;
3135
4141
  for (const s of e)
3136
- t ? (t.r1 = Math.min(t.r1, s.r1), t.c1 = Math.min(t.c1, s.c1), t.r2 = Math.max(t.r2, s.r2), t.c2 = Math.max(t.c2, s.c2)) : t = new A(s.r1, s.c1, s.r2, s.c2);
4142
+ t ? (t.r1 = Math.min(t.r1, s.r1), t.c1 = Math.min(t.c1, s.c1), t.r2 = Math.max(t.r2, s.r2), t.c2 = Math.max(t.c2, s.c2)) : t = new R(s.r1, s.c1, s.r2, s.c2);
3137
4143
  return t;
3138
4144
  }
3139
4145
  };
3140
- O.columnSeparatorChar = " ", O.rowSeparatorChar = `
4146
+ L.columnSeparatorChar = " ", L.rowSeparatorChar = `
3141
4147
  `;
3142
- let P = O;
4148
+ let P = L;
3143
4149
  class Be {
3144
4150
  constructor(e, t = 500) {
3145
4151
  this.tableScope = e, this.debounceDelay = t, new ResizeObserver(le(this.handleResize.bind(this), t)).observe(this.tableScope.hostElement);
@@ -3230,8 +4236,8 @@ class Pe {
3230
4236
  let s = 0;
3231
4237
  const o = [];
3232
4238
  e.forEach((h, d) => {
3233
- const u = new TextEncoder().encode(d), g = new TextEncoder().encode(h), b = new Uint8Array(30 + u.length), f = new DataView(b.buffer);
3234
- b.set([80, 75, 3, 4], 0), f.setUint16(4, 20, !0), f.setUint16(6, 0, !0), f.setUint16(8, 0, !0), f.setUint16(10, 0, !0), f.setUint16(12, 0, !0), f.setUint32(14, 0, !0), f.setUint32(18, g.length, !0), f.setUint32(22, g.length, !0), f.setUint16(26, u.length, !0), f.setUint16(28, 0, !0), b.set(u, 30), t.push(b, g), o.push({
4239
+ const m = new TextEncoder().encode(d), g = new TextEncoder().encode(h), b = new Uint8Array(30 + m.length), f = new DataView(b.buffer);
4240
+ b.set([80, 75, 3, 4], 0), f.setUint16(4, 20, !0), f.setUint16(6, 0, !0), f.setUint16(8, 0, !0), f.setUint16(10, 0, !0), f.setUint16(12, 0, !0), f.setUint32(14, 0, !0), f.setUint32(18, g.length, !0), f.setUint32(22, g.length, !0), f.setUint16(26, m.length, !0), f.setUint16(28, 0, !0), b.set(m, 30), t.push(b, g), o.push({
3235
4241
  path: d,
3236
4242
  offset: s,
3237
4243
  contentSize: g.length
@@ -3239,8 +4245,8 @@ class Pe {
3239
4245
  });
3240
4246
  const i = s;
3241
4247
  o.forEach((h) => {
3242
- const d = new TextEncoder().encode(h.path), u = new Uint8Array(46 + d.length), g = new DataView(u.buffer);
3243
- u.set([80, 75, 1, 2], 0), g.setUint16(4, 20, !0), g.setUint16(6, 20, !0), g.setUint16(8, 0, !0), g.setUint16(10, 0, !0), g.setUint16(12, 0, !0), g.setUint16(14, 0, !0), g.setUint32(16, 0, !0), g.setUint32(20, h.contentSize, !0), g.setUint32(24, h.contentSize, !0), g.setUint16(28, d.length, !0), g.setUint16(30, 0, !0), g.setUint16(32, 0, !0), g.setUint16(34, 0, !0), g.setUint16(36, 0, !0), g.setUint32(38, 0, !0), g.setUint32(42, h.offset, !0), u.set(d, 46), t.push(u), s += u.length;
4248
+ const d = new TextEncoder().encode(h.path), m = new Uint8Array(46 + d.length), g = new DataView(m.buffer);
4249
+ m.set([80, 75, 1, 2], 0), g.setUint16(4, 20, !0), g.setUint16(6, 20, !0), g.setUint16(8, 0, !0), g.setUint16(10, 0, !0), g.setUint16(12, 0, !0), g.setUint16(14, 0, !0), g.setUint32(16, 0, !0), g.setUint32(20, h.contentSize, !0), g.setUint32(24, h.contentSize, !0), g.setUint16(28, d.length, !0), g.setUint16(30, 0, !0), g.setUint16(32, 0, !0), g.setUint16(34, 0, !0), g.setUint16(36, 0, !0), g.setUint32(38, 0, !0), g.setUint32(42, h.offset, !0), m.set(d, 46), t.push(m), s += m.length;
3244
4250
  });
3245
4251
  const r = new Uint8Array(22), l = new DataView(r.buffer);
3246
4252
  r.set([80, 75, 5, 6], 0), l.setUint16(4, 0, !0), l.setUint16(6, 0, !0), l.setUint16(8, o.length, !0), l.setUint16(10, o.length, !0), l.setUint32(12, s - i, !0), l.setUint32(16, i, !0), l.setUint16(20, 0, !0), t.push(r);
@@ -3258,11 +4264,11 @@ class Pe {
3258
4264
  class U extends xe {
3259
4265
  constructor(e, t, s, o, i, r = new P(), l = new Pe()) {
3260
4266
  var c;
3261
- if (super(e, t, new ne(s), o), this.eventListener = i, this.copyService = r, this.excelService = l, this.licenseManager = k.getInstance(), this.selectionService = new Ee(this), this.api = new ge(this), this.mouseStartAction = "", this.mouseStartWidth = -1, this.mouseStartColumnIndex = -1, this.dragFrom = -1, this.dragTo = -1, this.lastDragFrom = -1, this.lastDragTo = -1, this.firstDraggingRendering = !0, this.lastContextmenu = Date.now(), t.setTableScope(this), i || (this.eventListener = new K()), (c = this.tableOptions) != null && c.autoRestoreOptions) {
4267
+ if (super(e, t, new ne(s), o), this.eventListener = i, this.copyService = r, this.excelService = l, this.licenseManager = I.getInstance(), this.selectionService = new Ae(this), this.api = new ge(this), this.mouseStartAction = "", this.mouseStartWidth = -1, this.mouseStartColumnIndex = -1, this.dragFrom = -1, this.dragTo = -1, this.lastDragFrom = -1, this.lastDragTo = -1, this.firstDraggingRendering = !0, this.lastContextmenu = Date.now(), t.setTableScope(this), i || (this.eventListener = new K()), (c = this.tableOptions) != null && c.autoRestoreOptions) {
3262
4268
  const h = this.tableOptions.autoRestoreOptions, d = h.getStorageKeyFn;
3263
4269
  d && (h.autoRestoreScrollPosition && (this.storeScrollPosStateService = new fe(d)), h.autoRestoreCollapsedExpandedState && (this.storeStateCollapsedExpandService = new me(d)), h.autoRestoreSortingState && (this.storeSortingService = new be(d)));
3264
4270
  }
3265
- this.mouseHandler = new de(this), this.inputHandler = new ve(this), this.resizeHandler = new Be(this, o.resizeEventDebounceDelay), this.shortcutService = new De(this), this.shortcutService.addListener(this.selectionService);
4271
+ this.mouseHandler = new de(this), this.inputHandler = new ve(this), this.resizeHandler = new Be(this, o.resizeEventDebounceDelay), this.shortcutService = new Fe(this), this.shortcutService.addListener(this.selectionService);
3266
4272
  const a = this.getSelectionModel ? this.getSelectionModel() : void 0;
3267
4273
  a && a.addEventSelectionChangedListener(this);
3268
4274
  const n = this.getFocusModel ? this.getFocusModel() : void 0;
@@ -3414,7 +4420,7 @@ class U extends xe {
3414
4420
  toggleExpandCollapseAll(e = !0) {
3415
4421
  var s;
3416
4422
  const t = this.tableModel.getBodyModel();
3417
- V(t) && (t.toggleExpandCollapseAll(e), this.repaint(), (s = this.storeStateCollapsedExpandService) == null || s.collapsedStateAll(e));
4423
+ $(t) && (t.toggleExpandCollapseAll(e), this.repaint(), (s = this.storeStateCollapsedExpandService) == null || s.collapsedStateAll(e));
3418
4424
  }
3419
4425
  /**
3420
4426
  * Toggles the checkbox state of a specific row in a table.
@@ -3630,7 +4636,7 @@ class U extends xe {
3630
4636
  const s = this.tableOptions.autoRestoreOptions, o = s.getRowId;
3631
4637
  if (s.autoRestoreCollapsedExpandedState && o) {
3632
4638
  const i = this.storeStateCollapsedExpandService.collapsedExpandedStateGet(), r = this.tableModel.getAreaModel("body");
3633
- if (V(r)) {
4639
+ if ($(r)) {
3634
4640
  const l = r, a = r.getRowCount();
3635
4641
  for (let n = 0; n < a; n++) {
3636
4642
  const c = r.getRowByIndex(n);
@@ -3683,9 +4689,6 @@ class U extends xe {
3683
4689
  sort(e) {
3684
4690
  this.tableModel.sort(e);
3685
4691
  }
3686
- getDisplayedRowCount() {
3687
- return this.displayedRowCount;
3688
- }
3689
4692
  /**
3690
4693
  * Ensures that a specific row is visible in the viewport by scrolling if necessary.
3691
4694
  * This method checks if the target row is within the currently visible range and
@@ -3738,16 +4741,13 @@ class U extends xe {
3738
4741
  * @see {@link getDisplayedRowCount} - Related method for getting visible row count
3739
4742
  */
3740
4743
  ensureRowIsVisible(e) {
3741
- const t = this.firstVisibleRowIndex, s = this.firstVisibleRowIndex + this.displayedRowCount - 1;
3742
- return e < t ? (this.scrollToIndex(0, e + 2), !0) : e > s ? (this.scrollToIndex(0, e + this.displayedRowCount - 3), !0) : !1;
3743
- }
3744
- getFirstVisibleRowIndex() {
3745
- return this.firstVisibleRowIndex;
4744
+ const t = this.getFirstFullVisibleRowIndex(), s = this.getLastFullVisibleRowIndex(), o = this.getDisplayedRowCount();
4745
+ return e < t ? (this.scrollToIndex(0, e), !0) : e > s ? (this.scrollToIndex(0, e - o + 1), !0) : !1;
3746
4746
  }
3747
4747
  }
3748
- const W = class W {
4748
+ const V = class V {
3749
4749
  };
3750
- W.themes = ["light", "combat", "paper", "blackboard"], W.vars = {
4750
+ V.themes = ["light", "combat", "paper", "blackboard"], V.vars = {
3751
4751
  light: `html[data-theme="light"] {
3752
4752
  --ge-table-bg: rgba(255,255,255, 0.5);
3753
4753
  --ge-table-header-west-bg: rgba(233, 233, 233, 0.5);
@@ -3981,15 +4981,15 @@ W.themes = ["light", "combat", "paper", "blackboard"], W.vars = {
3981
4981
  --ge-table-drop-zone-bg: #758129;
3982
4982
  }`
3983
4983
  };
3984
- let Y = W;
3985
- const H = class H {
4984
+ let Y = V;
4985
+ const W = class W {
3986
4986
  constructor(e = new te()) {
3987
4987
  this.headerGroupOptions = e;
3988
4988
  }
3989
4989
  render(e, t, s, o, i, r, l) {
3990
4990
  const a = r != null && r.data ? r.data : "";
3991
4991
  if (r) {
3992
- const { toggle: n, visibility: c, closed: h } = r, d = n ? H.toggleHeaderGroup : "";
4992
+ const { toggle: n, visibility: c, closed: h } = r, d = n ? W.toggleHeaderGroup : "";
3993
4993
  this.addText(e, o, t, s, a, d), n && c !== "always" && this.addArrowDiv(l, e, !h, t, s, o, d);
3994
4994
  } else
3995
4995
  this.addText(e, o, t, s, a, "");
@@ -4021,8 +5021,8 @@ const H = class H {
4021
5021
  }
4022
5022
  }
4023
5023
  };
4024
- H.toggleHeaderGroup = "toggleHeaderGroup";
4025
- let q = H;
5024
+ W.toggleHeaderGroup = "toggleHeaderGroup";
5025
+ let q = W;
4026
5026
  function Ne({
4027
5027
  tableModel: p,
4028
5028
  tableOptions: e = new se(),
@@ -4038,13 +5038,13 @@ function Ne({
4038
5038
  tableReady: h,
4039
5039
  licenseKey: d
4040
5040
  }) {
4041
- const u = ie(null);
5041
+ const m = ie(null);
4042
5042
  let g = !1;
4043
5043
  re(() => {
4044
- u.current && !g && (b(u.current), g = !0);
5044
+ m.current && !g && (b(m.current), g = !0);
4045
5045
  });
4046
5046
  const b = (f) => {
4047
- const m = {
5047
+ const u = {
4048
5048
  onSelectionChanged(S) {
4049
5049
  n && n(S);
4050
5050
  },
@@ -4077,14 +5077,14 @@ function Ne({
4077
5077
  p,
4078
5078
  new ee(),
4079
5079
  e,
4080
- m
5080
+ u
4081
5081
  );
4082
- w.firstInit(), h && h(w.getApi()), d && k.getInstance().setLicenseKey(d);
5082
+ w.firstInit(), h && h(w.getApi()), d && I.getInstance().setLicenseKey(d);
4083
5083
  };
4084
5084
  return /* @__PURE__ */ oe(
4085
5085
  "div",
4086
5086
  {
4087
- ref: u,
5087
+ ref: m,
4088
5088
  className: "container-div",
4089
5089
  style: {
4090
5090
  width: "100%",
@@ -4096,23 +5096,23 @@ function Ne({
4096
5096
  }
4097
5097
  );
4098
5098
  }
4099
- var I = {}, J;
4100
- function We() {
4101
- if (J) return I;
5099
+ var k = {}, J;
5100
+ function Ve() {
5101
+ if (J) return k;
4102
5102
  J = 1;
4103
5103
  var p = ae;
4104
5104
  if (process.env.NODE_ENV === "production")
4105
- I.createRoot = p.createRoot, I.hydrateRoot = p.hydrateRoot;
5105
+ k.createRoot = p.createRoot, k.hydrateRoot = p.hydrateRoot;
4106
5106
  else {
4107
5107
  var e = p.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
4108
- I.createRoot = function(t, s) {
5108
+ k.createRoot = function(t, s) {
4109
5109
  e.usingClientEntryPoint = !0;
4110
5110
  try {
4111
5111
  return p.createRoot(t, s);
4112
5112
  } finally {
4113
5113
  e.usingClientEntryPoint = !1;
4114
5114
  }
4115
- }, I.hydrateRoot = function(t, s, o) {
5115
+ }, k.hydrateRoot = function(t, s, o) {
4116
5116
  e.usingClientEntryPoint = !0;
4117
5117
  try {
4118
5118
  return p.hydrateRoot(t, s, o);
@@ -4121,9 +5121,9 @@ function We() {
4121
5121
  }
4122
5122
  };
4123
5123
  }
4124
- return I;
5124
+ return k;
4125
5125
  }
4126
- var He = We();
5126
+ var We = Ve();
4127
5127
  class ze {
4128
5128
  constructor(e) {
4129
5129
  this.Component = e, console.info(e);
@@ -4136,7 +5136,7 @@ class ze {
4136
5136
  areaIdent: o,
4137
5137
  areaModel: i,
4138
5138
  cellValue: r
4139
- }, n = He.createRoot(e, {});
5139
+ }, n = We.createRoot(e, {});
4140
5140
  return n.render(this.Component(a)), () => {
4141
5141
  n.unmount();
4142
5142
  };