@guiexpert/preact-table 10.1.79 → 10.1.81

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 (2) hide show
  1. package/index.js +1013 -41
  2. package/package.json +5 -3
package/index.js CHANGED
@@ -539,28 +539,128 @@ class je {
539
539
  }
540
540
  }
541
541
  class I extends Ue {
542
+ /**
543
+ * Creates an instance of AreaModelObjectArray.
544
+ *
545
+ * @param {AreaIdent} areaIdent - Identifies which area of the table this model represents ('header', 'body', or 'footer')
546
+ * @param {T[]} rows - The array of objects that represent the rows in this area
547
+ * @param {number} defaultRowHeight - The default height for rows in this area (in pixels)
548
+ * @param {ColumnDefIf[]} [columnDefs=[]] - Definitions for the columns in this area
549
+ * @param {string} [selectedRowClass='ge-selected-row'] - CSS class to apply to selected rows
550
+ * @param {string} [focusedRowClass='ge-focused-row'] - CSS class to apply to the focused row
551
+ *
552
+ * @example
553
+ * const rows = [
554
+ * { id: 1, name: 'John', age: 30 },
555
+ * { id: 2, name: 'Jane', age: 25 }
556
+ * ];
557
+ *
558
+ * const columnDefs = [
559
+ * { property: 'id', headerLabel: 'ID', width: 50 },
560
+ * { property: 'name', headerLabel: 'Name', width: 150 },
561
+ * { property: 'age', headerLabel: 'Age', width: 100 }
562
+ * ];
563
+ *
564
+ * const bodyAreaModel = new AreaModelObjectArray(
565
+ * 'body',
566
+ * rows,
567
+ * 30,
568
+ * columnDefs
569
+ * );
570
+ */
542
571
  constructor(e, t, s, o = [], i = "ge-selected-row", r = "ge-focused-row") {
543
572
  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 je(), this._focusedRowIndex = 0, this.filteredRows = [...t], this.properties = o.map((n) => n.property);
544
573
  }
574
+ /**
575
+ * Gets the index of the currently focused row.
576
+ *
577
+ * @returns {number} The index of the focused row
578
+ *
579
+ * @example
580
+ * const focusedRowIndex = bodyAreaModel.getFocusedRowIndex();
581
+ * console.log(`The focused row is at index ${focusedRowIndex}`);
582
+ */
545
583
  getFocusedRowIndex() {
546
584
  return this._focusedRowIndex;
547
585
  }
586
+ /**
587
+ * Sets the index of the focused row.
588
+ * This will apply the focused row styling to the specified row.
589
+ *
590
+ * @param {number} value - The index of the row to focus
591
+ *
592
+ * @example
593
+ * // Focus the second row (index 1)
594
+ * bodyAreaModel.setFocusedRowIndex(1);
595
+ */
548
596
  setFocusedRowIndex(e) {
549
597
  this._focusedRowIndex = e;
550
598
  }
599
+ /**
600
+ * Replaces the current rows array with a new one.
601
+ * This also resets the filtered rows to match the new rows array.
602
+ *
603
+ * @param {T[]} rows - The new array of row objects
604
+ *
605
+ * @example
606
+ * // Replace the current rows with new data
607
+ * const newRows = [
608
+ * { id: 4, name: 'Alice', age: 35 },
609
+ * { id: 5, name: 'Charlie', age: 45 }
610
+ * ];
611
+ * bodyAreaModel.setRows(newRows);
612
+ */
551
613
  setRows(e) {
552
614
  this.rows = e, this.filteredRows = [...e];
553
615
  }
616
+ /**
617
+ * Filters both the original rows and filtered rows arrays using the provided predicate function.
618
+ * Unlike `externalFilterChanged`, this method permanently modifies the original rows array.
619
+ *
620
+ * @param {(row: T) => boolean} predict - A function that returns true for rows to keep and false for rows to filter out
621
+ *
622
+ * @example
623
+ * // Remove all rows where age is less than 30
624
+ * bodyAreaModel.filterRowsByPredict(row => row.age >= 30);
625
+ */
554
626
  filterRowsByPredict(e) {
555
627
  this.rows = this.rows.filter(e), this.filteredRows = this.filteredRows.filter(e);
556
628
  }
557
629
  /**
558
- * return row count of filtered rows
630
+ * Returns the number of rows in the filtered rows array.
631
+ * This is used to determine how many rows should be rendered in the table.
632
+ *
633
+ * @returns {number} The number of rows in the filtered rows array
634
+ *
635
+ * @example
636
+ * const rowCount = bodyAreaModel.getRowCount();
637
+ * console.log(`The table has ${rowCount} rows`);
559
638
  */
560
639
  getRowCount() {
561
640
  var e;
562
641
  return ((e = this.filteredRows) == null ? void 0 : e.length) ?? 0;
563
642
  }
643
+ /**
644
+ * Gets the value at the specified row and column indices.
645
+ * This method handles tree rows and nested properties.
646
+ *
647
+ * @param {number} rowIndex - The index of the row
648
+ * @param {number} columnIndex - The index of the column
649
+ * @returns {any} The value at the specified cell, or an empty string if not found
650
+ *
651
+ * @example
652
+ * // Get the value in the first row, second column
653
+ * const value = bodyAreaModel.getValueAt(0, 1);
654
+ * console.log(`The value is: ${value}`);
655
+ *
656
+ * @example
657
+ * // Iterate through all cells in a row
658
+ * const rowIndex = 0;
659
+ * for (let colIndex = 0; colIndex < columnDefs.length; colIndex++) {
660
+ * const value = bodyAreaModel.getValueAt(rowIndex, colIndex);
661
+ * console.log(`Cell (${rowIndex}, ${colIndex}): ${value}`);
662
+ * }
663
+ */
564
664
  getValueAt(e, t) {
565
665
  const s = this.properties[t];
566
666
  let o = this.filteredRows[e];
@@ -569,46 +669,176 @@ class I extends Ue {
569
669
  /**
570
670
  * Retrieves the filtered and sorted rows from the dataset.
571
671
  * These rows are used for rendering the table.
672
+ * Unlike `getAllRows()`, this method returns only the rows that match any applied filters.
572
673
  *
573
- * @return {T[]} An array containing the filtered (and sorted) rows.
674
+ * @returns {T[]} An array containing the filtered (and sorted) rows
675
+ *
676
+ * @example
677
+ * // Get all filtered rows
678
+ * const filteredRows = bodyAreaModel.getFilteredRows();
679
+ *
680
+ * // Count rows that match a certain condition
681
+ * const adultsCount = filteredRows.filter(row => row.age >= 18).length;
574
682
  */
575
683
  getFilteredRows() {
576
684
  return this.filteredRows;
577
685
  }
686
+ /**
687
+ * Returns the original, unfiltered array of rows.
688
+ * This can be useful when you need to access all data regardless of any applied filters.
689
+ *
690
+ * @returns {T[]} The original array of row objects
691
+ *
692
+ * @example
693
+ * // Get all rows, including those filtered out
694
+ * const allRows = bodyAreaModel.getAllRows();
695
+ *
696
+ * // Calculate average age across all rows
697
+ * const totalAge = allRows.reduce((sum, row) => sum + row.age, 0);
698
+ * const averageAge = totalAge / allRows.length;
699
+ */
578
700
  getAllRows() {
579
701
  return this.rows;
580
702
  }
581
703
  /**
582
704
  * Returns the first row from the filtered rows that matches the given criteria based on the provided predicate function.
705
+ * This method only searches within the filtered rows, not the original rows array.
583
706
  *
584
707
  * @param {Partial<T>} criteria - A partial object containing the search criteria
585
708
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
586
709
  * and returns true if the row matches the criteria
587
710
  * @returns {T | undefined} The first matching row, or undefined if no match is found
711
+ *
712
+ * @example
713
+ * // Find a user by name in the filtered rows
714
+ * const criteria = { name: 'John' };
715
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
716
+ * criteria,
717
+ * (criteria, row) => row.name === criteria.name
718
+ * );
719
+ *
720
+ * @example
721
+ * // Find a user by age range in the filtered rows
722
+ * const criteria = { minAge: 25, maxAge: 35 };
723
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
724
+ * criteria,
725
+ * (criteria, row) => row.age >= criteria.minAge && row.age <= criteria.maxAge
726
+ * );
588
727
  */
589
728
  findRowFromFilteredRowsByAllCriteria(e, t) {
590
729
  return this.getFilteredRows().find((s) => t(e, s));
591
730
  }
592
731
  /**
593
732
  * Searches through all rows to find a row that matches the given criteria based on the predicate function.
733
+ * This method searches within the original rows array, including rows that may have been filtered out.
594
734
  *
595
735
  * @param {Partial<T>} criteria - A partial object containing the search criteria
596
736
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
597
737
  * and returns true if the row matches the criteria
598
738
  * @returns {T | undefined} The first matching row from all rows, or undefined if no match is found
739
+ *
740
+ * @example
741
+ * // Find a user by ID in all rows
742
+ * const criteria = { id: 42 };
743
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
744
+ * criteria,
745
+ * (criteria, row) => row.id === criteria.id
746
+ * );
747
+ *
748
+ * @example
749
+ * // Find a user with a specific property value in all rows
750
+ * const criteria = { department: 'Engineering', role: 'Manager' };
751
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
752
+ * criteria,
753
+ * (criteria, row) => row.department === criteria.department && row.role === criteria.role
754
+ * );
599
755
  */
600
756
  findRowFromAllRowsByAllCriteria(e, t) {
601
757
  return this.getAllRows().find((s) => t(e, s));
602
758
  }
759
+ /**
760
+ * Returns the height of the row at the specified index.
761
+ * This implementation always returns the default row height.
762
+ * Override this method in subclasses to support variable row heights.
763
+ *
764
+ * @param {number} _rowIndex - The index of the row (unused in this implementation)
765
+ * @returns {number} The height of the row in pixels
766
+ *
767
+ * @example
768
+ * const rowHeight = bodyAreaModel.getRowHeight(0);
769
+ * console.log(`The first row has a height of ${rowHeight}px`);
770
+ */
603
771
  getRowHeight(e) {
604
772
  return this.defaultRowHeight;
605
773
  }
774
+ /**
775
+ * Returns the row object at the specified index from the filtered rows array.
776
+ * This method overrides the parent class implementation.
777
+ *
778
+ * @param {number} rowIndex - The index of the row to retrieve
779
+ * @returns {any} The row object at the specified index, or undefined if the index is out of bounds
780
+ *
781
+ * @example
782
+ * // Get the first row object
783
+ * const row = bodyAreaModel.getRowByIndex(0);
784
+ * console.log('First row:', row);
785
+ *
786
+ * @example
787
+ * // Iterate through all rows
788
+ * for (let i = 0; i < bodyAreaModel.getRowCount(); i++) {
789
+ * const row = bodyAreaModel.getRowByIndex(i);
790
+ * console.log(`Row ${i}:`, row);
791
+ * }
792
+ */
606
793
  getRowByIndex(e) {
607
794
  return this.filteredRows[e];
608
795
  }
796
+ /**
797
+ * Applies an external filter function to the rows array.
798
+ * This method updates the filtered rows array without modifying the original rows array.
799
+ *
800
+ * @param {FilterFunction<any>} predictFn - A function that returns true for rows to keep and false for rows to filter out
801
+ *
802
+ * @example
803
+ * // Filter rows where age is greater than 30
804
+ * bodyAreaModel.externalFilterChanged(row => row.age > 30);
805
+ *
806
+ * @example
807
+ * // Filter rows based on a search term
808
+ * const searchTerm = 'john';
809
+ * bodyAreaModel.externalFilterChanged(row =>
810
+ * row.name.toLowerCase().includes(searchTerm.toLowerCase())
811
+ * );
812
+ *
813
+ * @example
814
+ * // Clear all filters
815
+ * bodyAreaModel.externalFilterChanged(() => true);
816
+ */
609
817
  externalFilterChanged(e) {
610
818
  this.filteredRows = this.rows ? this.rows.filter(e) : [];
611
819
  }
820
+ /**
821
+ * Sorts the filtered rows based on the provided sort items.
822
+ * This method supports sorting by multiple columns with different sort directions.
823
+ *
824
+ * @param {SortItem[]} sortItems - An array of sort items, each containing a column index and sort state
825
+ * @returns {boolean} Always returns true to indicate sorting was performed
826
+ *
827
+ * @example
828
+ * // Sort by age in ascending order
829
+ * bodyAreaModel.doSort([{ columnIndex: 2, sortState: 'asc' }]);
830
+ *
831
+ * @example
832
+ * // Sort by name in descending order, then by age in ascending order
833
+ * bodyAreaModel.doSort([
834
+ * { columnIndex: 1, sortState: 'desc' },
835
+ * { columnIndex: 2, sortState: 'asc' }
836
+ * ]);
837
+ *
838
+ * @example
839
+ * // Clear sorting
840
+ * bodyAreaModel.doSort([{ columnIndex: 0, sortState: 'none' }]);
841
+ */
612
842
  doSort(e) {
613
843
  for (const t of e) {
614
844
  const { columnIndex: s, sortState: o } = t, i = o === "asc" ? 1 : o === "desc" ? -1 : 0, r = this.properties[s];
@@ -616,20 +846,110 @@ class I extends Ue {
616
846
  }
617
847
  return !0;
618
848
  }
849
+ /**
850
+ * Sorts the filtered rows using a custom comparator function.
851
+ * This method provides more flexibility than `doSort()` for complex sorting logic.
852
+ *
853
+ * @param {(a: T, b: T) => number} compareFn - A function that compares two rows and returns a number:
854
+ * - Negative if a should come before b
855
+ * - Positive if a should come after b
856
+ * - Zero if they are equivalent for sorting purposes
857
+ *
858
+ * @example
859
+ * // Sort by name length
860
+ * bodyAreaModel.sort((a, b) => a.name.length - b.name.length);
861
+ *
862
+ * @example
863
+ * // Sort by a computed value
864
+ * bodyAreaModel.sort((a, b) => {
865
+ * const scoreA = a.wins * 3 + a.draws;
866
+ * const scoreB = b.wins * 3 + b.draws;
867
+ * return scoreB - scoreA; // Descending order
868
+ * });
869
+ */
619
870
  sort(e) {
620
871
  this.filteredRows = this.filteredRows.sort(e);
621
872
  }
873
+ /**
874
+ * Gets a value from an object using a property path.
875
+ * This method supports accessing nested properties using dot notation (e.g., 'person.name').
876
+ *
877
+ * @param {T} t - The object to get the value from
878
+ * @param {string} property - The property path to access (e.g., 'name' or 'person.contact.email')
879
+ * @returns {any} The value at the specified property path, or undefined if not found
880
+ *
881
+ * @example
882
+ * const user = { id: 1, name: 'John', contact: { email: 'john@example.com' } };
883
+ *
884
+ * // Access simple property
885
+ * const name = bodyAreaModel.getValueByT(user, 'name');
886
+ * console.log(name); // 'John'
887
+ *
888
+ * // Access nested property
889
+ * const email = bodyAreaModel.getValueByT(user, 'contact.email');
890
+ * console.log(email); // 'john@example.com'
891
+ */
622
892
  getValueByT(e, t) {
623
893
  if (e && t)
624
894
  return t.includes(".") ? this.getPropertyValue(e, t.split(".")) : e[t];
625
895
  }
896
+ /**
897
+ * Changes the order of columns by moving a column from one position to another.
898
+ * This method updates both the properties array and calls the parent class implementation.
899
+ *
900
+ * @param {number} sourceColumnIndex - The index of the column to move
901
+ * @param {number} targetColumnIndex - The index where the column should be moved to
902
+ *
903
+ * @example
904
+ * // Move the second column (index 1) to the fourth position (index 3)
905
+ * bodyAreaModel.changeColumnOrder(1, 3);
906
+ *
907
+ * @example
908
+ * // Move the last column to the first position
909
+ * const lastIndex = bodyAreaModel.columnDefs.length - 1;
910
+ * bodyAreaModel.changeColumnOrder(lastIndex, 0);
911
+ */
626
912
  changeColumnOrder(e, t) {
627
913
  this.arrayMove(this.properties, e, t), super.changeColumnOrder(e, t);
628
914
  }
915
+ /**
916
+ * Gets the custom CSS classes that should be applied to a cell.
917
+ * This method extends the parent class implementation to add selection and focus classes.
918
+ *
919
+ * @param {number} rowIndex - The index of the row
920
+ * @param {number} _columnIndex - The index of the column (unused in this implementation)
921
+ * @returns {string[]} An array of CSS class names to apply to the cell
922
+ *
923
+ * @example
924
+ * // Get the CSS classes for a cell
925
+ * const classes = bodyAreaModel.getCustomClassesAt(1, 2);
926
+ * console.log('CSS classes:', classes);
927
+ *
928
+ * @example
929
+ * // Apply the classes to a cell element
930
+ * const cellElement = document.createElement('div');
931
+ * const classes = bodyAreaModel.getCustomClassesAt(rowIndex, columnIndex);
932
+ * cellElement.classList.add(...classes);
933
+ */
629
934
  getCustomClassesAt(e, t) {
630
935
  const s = super.getCustomClassesAt(e, t);
631
936
  return this.getRowByIndex(e).selected && s.push(this.selectedRowClass), this._focusedRowIndex === e && s.push(this.focusedRowClass), s;
632
937
  }
938
+ /**
939
+ * Creates a comparator function for sorting rows based on a property and sort direction.
940
+ * This method supports custom sort comparators defined in column definitions.
941
+ *
942
+ * @param {string} property - The property to sort by
943
+ * @param {number} f - The sort direction factor: 1 for ascending, -1 for descending, 0 for no sorting
944
+ * @returns {(a: T, b: T) => number} A comparator function that compares two rows
945
+ *
946
+ * @example
947
+ * // Create a comparator for sorting by name in ascending order
948
+ * const comparator = bodyAreaModel.genericFlatTableSortComparator('name', 1);
949
+ *
950
+ * // Sort the rows using the comparator
951
+ * const sortedRows = [...bodyAreaModel.getFilteredRows()].sort(comparator);
952
+ */
633
953
  genericFlatTableSortComparator(e, t) {
634
954
  const s = this.columnDefs.find((o) => o.property === e);
635
955
  return (o, i) => {
@@ -637,6 +957,16 @@ class I extends Ue {
637
957
  return s != null && s.sortComparator ? t * s.sortComparator(r, n, o, i, t) : this.sorterService.genericSortComparator(r, n, t);
638
958
  };
639
959
  }
960
+ /**
961
+ * Recursively gets a value from an object using an array of property names.
962
+ * This is a helper method used by `getValueByT` to access nested properties.
963
+ *
964
+ * @param {any} o - The object to get the value from
965
+ * @param {string[]} props - An array of property names representing the path to the value
966
+ * @returns {any} The value at the specified property path, or undefined if not found
967
+ *
968
+ * @private
969
+ */
640
970
  getPropertyValue(e, t) {
641
971
  const s = t.shift(), o = e[s];
642
972
  return o && t.length ? this.getPropertyValue(o, t) : o;
@@ -647,41 +977,302 @@ class Xe {
647
977
  this.tableScope = e;
648
978
  }
649
979
  /**
650
- * Updates the cells in the table based on the provided events.
980
+ * Updates the cells in the table with the provided cell update events.
651
981
  *
652
- * @param {TableCellUpdateEventIf[]} events - The array of events representing the updates to perform on the cells.
653
- * @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.
982
+ * This method allows you to update specific cells in the table without requiring a full table repaint,
983
+ * which can significantly improve performance when updating large tables frequently.
654
984
  *
655
- * @return {void} - This method doesn't return anything.
985
+ * @param {TableCellUpdateEventIf[]} events - An array of cell update events, each defining a single cell update operation.
986
+ * Each event must specify:
987
+ * - area: The table area to update ('header', 'body', or 'footer')
988
+ * - rowIndex: The row index of the cell to update
989
+ * - columnIndex: The column index of the cell to update
990
+ * - value: The new value to set for the cell
991
+ * - cssClasses: Optional object mapping CSS class names to boolean values
992
+ * (true to add the class, false to remove it)
993
+ *
994
+ * @param {boolean} [repaintAll=false] - Whether to repaint the entire table after updating cells.
995
+ * - If true: All cells will be repainted after updating (slower but ensures visual consistency)
996
+ * - If false: Only the modified cells will be repainted (faster, recommended for frequent updates)
997
+ *
998
+ * @returns {void}
999
+ *
1000
+ * @example
1001
+ * // Update a single cell with a new value and CSS classes
1002
+ * tableApi.updateCells([{
1003
+ * area: 'body',
1004
+ * rowIndex: 3,
1005
+ * columnIndex: 2,
1006
+ * value: 42,
1007
+ * cssClasses: {
1008
+ * 'highlight': true, // Add 'highlight' class
1009
+ * 'error': false // Remove 'error' class if present
1010
+ * }
1011
+ * }]);
1012
+ *
1013
+ * @example
1014
+ * // Update multiple cells at once
1015
+ * tableApi.updateCells([
1016
+ * {
1017
+ * area: 'body',
1018
+ * rowIndex: 1,
1019
+ * columnIndex: 1,
1020
+ * value: 'New Value 1',
1021
+ * cssClasses: { 'updated': true }
1022
+ * },
1023
+ * {
1024
+ * area: 'body',
1025
+ * rowIndex: 2,
1026
+ * columnIndex: 3,
1027
+ * value: 'New Value 2',
1028
+ * cssClasses: { 'updated': true }
1029
+ * }
1030
+ * ]);
1031
+ *
1032
+ * @example
1033
+ * // Update cells and repaint the entire table
1034
+ * tableApi.updateCells([
1035
+ * { area: 'body', rowIndex: 0, columnIndex: 0, value: 'Hello', cssClasses: { 'bg-green-0': true } },
1036
+ * { area: 'body', rowIndex: 1, columnIndex: 1, value: 'World', cssClasses: { 'bg-red-0': true } }
1037
+ * ], true);
1038
+ *
1039
+ * @example
1040
+ * // High-performance animation example (update without full repaint)
1041
+ * function animateCell() {
1042
+ * const value = Math.sin(Date.now() / 1000) * 50;
1043
+ * const cssClasses = {
1044
+ * 'positive': value > 0,
1045
+ * 'negative': value < 0
1046
+ * };
1047
+ *
1048
+ * tableApi.updateCells([{
1049
+ * area: 'body',
1050
+ * rowIndex: 0,
1051
+ * columnIndex: 0,
1052
+ * value: Math.round(value),
1053
+ * cssClasses
1054
+ * }]);
1055
+ *
1056
+ * requestAnimationFrame(animateCell);
1057
+ * }
1058
+ * animateCell();
656
1059
  */
657
1060
  updateCells(e, t = !1) {
658
1061
  this.tableScope.updateCells(e, t);
659
1062
  }
660
1063
  /**
661
- * Notifies that the external filter has changed.
1064
+ * Notifies the table that an external filter has been changed and needs to be applied.
662
1065
  *
663
- * @return {void}
1066
+ * This method is used when an external filter condition (defined by `tableOptions.externalFilterFunction`)
1067
+ * has changed and the table needs to refresh its display to reflect the new filtering criteria.
1068
+ *
1069
+ * When called, this method:
1070
+ * 1. Applies the external filter function to all rows
1071
+ * 2. Clears the current selection (by default)
1072
+ * 3. Scrolls to the top of the table
1073
+ * 4. Recalculates table dimensions
1074
+ * 5. Repaints the table to display only the filtered rows
1075
+ *
1076
+ * @example
1077
+ * ```typescript
1078
+ * // Define an external filter function in your table options
1079
+ * const tableOptions = {
1080
+ * externalFilterFunction: (row: MyRowType) => {
1081
+ * // Return true to include the row, false to filter it out
1082
+ * return row.status === 'active';
1083
+ * }
1084
+ * };
1085
+ *
1086
+ * // Initialize your table with these options
1087
+ * const tableApi = new TableApi(tableScope);
1088
+ *
1089
+ * // Later, when filter criteria change (e.g., in a search input handler)
1090
+ * function onFilterTextChanged() {
1091
+ * // Update the filter function if needed
1092
+ * tableOptions.externalFilterFunction = (row: MyRowType) => {
1093
+ * return row.name.includes(searchText);
1094
+ * };
1095
+ *
1096
+ * // Apply the updated filter
1097
+ * tableApi.externalFilterChanged();
1098
+ * }
1099
+ * ```
1100
+ *
1101
+ * @returns {void}
1102
+ * @see TableScope.externalFilterChanged
664
1103
  */
665
1104
  externalFilterChanged() {
666
1105
  this.tableScope.externalFilterChanged();
667
1106
  }
668
1107
  /**
669
- * Scrolls the table body to the specified pixel coordinates.
1108
+ * Scrolls the table content to the specified pixel coordinates.
670
1109
  *
671
- * @param {number} px - The horizontal pixel coordinate to scroll to. Defaults to 0.
672
- * @param {number} py - The vertical pixel coordinate to scroll to. Defaults to 0.
673
- * @return {void}
1110
+ * This method allows programmatic scrolling of the table viewport to exact pixel positions.
1111
+ * It delegates the scrolling operation to the underlying TableScope instance.
1112
+ *
1113
+ * @param {number} px - The horizontal pixel coordinate to scroll to. Defaults to 0 (leftmost position).
1114
+ * @param {number} py - The vertical pixel coordinate to scroll to. Defaults to 0 (topmost position).
1115
+ * @returns {void}
1116
+ *
1117
+ * @example
1118
+ * // Scroll to the top-left corner of the table
1119
+ * tableApi.scrollToPixel(0, 0);
1120
+ *
1121
+ * @example
1122
+ * // Scroll 200 pixels horizontally and 150 pixels vertically
1123
+ * tableApi.scrollToPixel(200, 150);
1124
+ *
1125
+ * @example
1126
+ * // Scroll only vertically, keeping the current horizontal position
1127
+ * tableApi.scrollToPixel(undefined, 300);
1128
+ *
1129
+ * @example
1130
+ * // Example in a component that needs precise scrolling control
1131
+ * class TableScroller {
1132
+ * private tableApi: TableApi;
1133
+ *
1134
+ * constructor(tableApi: TableApi) {
1135
+ * this.tableApi = tableApi;
1136
+ * }
1137
+ *
1138
+ * scrollToPosition(x: number, y: number) {
1139
+ * // Scroll to exact pixel coordinates
1140
+ * this.tableApi.scrollToPixel(x, y);
1141
+ * }
1142
+ *
1143
+ * scrollHalfway() {
1144
+ * const tableModel = this.tableApi.getTableModel();
1145
+ * const totalWidth = tableModel.getContentWidthInPixel();
1146
+ * const totalHeight = tableModel.getContentHeightInPixel();
1147
+ *
1148
+ * // Scroll to the middle of the table content
1149
+ * this.tableApi.scrollToPixel(totalWidth / 2, totalHeight / 2);
1150
+ * }
1151
+ * }
1152
+ *
1153
+ * @example
1154
+ * // Advanced usage with animated scrolling
1155
+ * class SmoothScroller {
1156
+ * private tableApi: TableApi;
1157
+ * private animationFrameId: number | null = null;
1158
+ *
1159
+ * constructor(tableApi: TableApi) {
1160
+ * this.tableApi = tableApi;
1161
+ * }
1162
+ *
1163
+ * smoothScrollTo(targetX: number, targetY: number, duration: number = 500) {
1164
+ * // Cancel any ongoing animation
1165
+ * if (this.animationFrameId !== null) {
1166
+ * cancelAnimationFrame(this.animationFrameId);
1167
+ * }
1168
+ *
1169
+ * const startTime = performance.now();
1170
+ * const startX = this.tableApi.getTableScope().getScrollLeft();
1171
+ * const startY = this.tableApi.getTableScope().getScrollTop();
1172
+ * const distanceX = targetX - startX;
1173
+ * const distanceY = targetY - startY;
1174
+ *
1175
+ * const step = (currentTime: number) => {
1176
+ * const elapsed = currentTime - startTime;
1177
+ * const progress = Math.min(elapsed / duration, 1);
1178
+ *
1179
+ * // Use easing function for smooth animation
1180
+ * const easeProgress = 1 - Math.pow(1 - progress, 3); // Cubic ease-out
1181
+ *
1182
+ * const currentX = startX + distanceX * easeProgress;
1183
+ * const currentY = startY + distanceY * easeProgress;
1184
+ *
1185
+ * this.tableApi.scrollToPixel(currentX, currentY);
1186
+ *
1187
+ * if (progress < 1) {
1188
+ * this.animationFrameId = requestAnimationFrame(step);
1189
+ * } else {
1190
+ * this.animationFrameId = null;
1191
+ * }
1192
+ * };
1193
+ *
1194
+ * this.animationFrameId = requestAnimationFrame(step);
1195
+ * }
1196
+ *
1197
+ * cancelAnimation() {
1198
+ * if (this.animationFrameId !== null) {
1199
+ * cancelAnimationFrame(this.animationFrameId);
1200
+ * this.animationFrameId = null;
1201
+ * }
1202
+ * }
1203
+ * }
1204
+ *
1205
+ * @see {@link scrollToIndex} - For scrolling based on row and column indices
1206
+ * @see {@link ensureRowIsVisible} - For scrolling to make a specific row visible
674
1207
  */
675
1208
  scrollToPixel(e = 0, t = 0) {
676
1209
  this.tableScope.scrollToPixel(e, t);
677
1210
  }
678
1211
  /**
679
- * Scrolls to the specified index in both horizontal and vertical directions.
1212
+ * Scrolls the table to display the specified row and column indices at the top-left corner of the viewport.
680
1213
  *
681
- * @param {number} indexX - The index of the column to scroll to in the horizontal direction. Default is 0.
682
- * @param {number} indexY - The index of the row to scroll to in the vertical direction. Default is 0.
1214
+ * This method allows programmatic scrolling to a specific position in the table grid based on row and column indices.
1215
+ * It uses the underlying TableScope's scrolling mechanism to navigate to the target location.
683
1216
  *
684
- * @return undefined
1217
+ * @param {number} indexX - The horizontal index (column) to scroll to. Defaults to 0 (leftmost column).
1218
+ * @param {number} indexY - The vertical index (row) to scroll to. Defaults to 0 (topmost row).
1219
+ * @returns {void}
1220
+ *
1221
+ * @example
1222
+ * // Scroll to the 5th row, keeping the current horizontal scroll position
1223
+ * tableApi.scrollToIndex(0, 5);
1224
+ *
1225
+ * @example
1226
+ * // Scroll to column 3, row 10
1227
+ * tableApi.scrollToIndex(3, 10);
1228
+ *
1229
+ * @example
1230
+ * // Example in a component that needs to navigate to specific content
1231
+ * class TableNavigator {
1232
+ * private tableApi: TableApi;
1233
+ *
1234
+ * constructor(tableApi: TableApi) {
1235
+ * this.tableApi = tableApi;
1236
+ * }
1237
+ *
1238
+ * goToCell(columnIndex: number, rowIndex: number) {
1239
+ * // Navigate directly to the specified cell position
1240
+ * this.tableApi.scrollToIndex(columnIndex, rowIndex);
1241
+ *
1242
+ * // Optional: Select the cell after navigating to it
1243
+ * const selectionModel = this.tableApi.getSelectionModel();
1244
+ * if (selectionModel) {
1245
+ * selectionModel.selectCell(rowIndex, columnIndex);
1246
+ * }
1247
+ * }
1248
+ * }
1249
+ *
1250
+ * @example
1251
+ * // Advanced usage with search functionality
1252
+ * class TableSearcher {
1253
+ * findAndScrollToMatch(searchTerm: string) {
1254
+ * const tableModel = this.tableApi.getTableModel();
1255
+ * const bodyModel = tableModel.getAreaModel('body');
1256
+ *
1257
+ * // Search for the term in the table data
1258
+ * for (let row = 0; row < bodyModel.getRowCount(); row++) {
1259
+ * for (let col = 0; col < tableModel.getColumnCount(); col++) {
1260
+ * const cellContent = bodyModel.getValueAt(row, col)?.toString() || '';
1261
+ *
1262
+ * if (cellContent.includes(searchTerm)) {
1263
+ * // Found a match, scroll to it
1264
+ * this.tableApi.scrollToIndex(col, row);
1265
+ * return true;
1266
+ * }
1267
+ * }
1268
+ * }
1269
+ *
1270
+ * return false; // No match found
1271
+ * }
1272
+ * }
1273
+ *
1274
+ * @see {@link scrollToPixel} - For scrolling to specific pixel coordinates
1275
+ * @see {@link ensureRowIsVisible} - For scrolling to make a specific row visible
685
1276
  */
686
1277
  scrollToIndex(e = 0, t = 0) {
687
1278
  this.tableScope.scrollToIndex(e, t);
@@ -742,19 +1333,71 @@ class Xe {
742
1333
  /**
743
1334
  * Repaints the table.
744
1335
  *
745
- * This method calls the repaint method of the tableScope object
746
- * to update and redraw the table based on the latest data.
1336
+ * This method refreshes the visual representation of the table by delegating to the
1337
+ * tableScope's repaint functionality. Use this method whenever the table's visual state
1338
+ * needs to be updated after data changes, selection changes, or any modifications that
1339
+ * affect the rendered output.
1340
+ *
1341
+ * Repainting the table ensures that all visible cells, rows, and styling reflect the
1342
+ * current state of the underlying data model and configuration settings.
1343
+ *
1344
+ * @example
1345
+ * // Update data and repaint the table
1346
+ * const tableApi = new TableApi(tableScope);
1347
+ * tableApi.setRows(newData);
1348
+ * tableApi.repaint();
1349
+ *
1350
+ * @example
1351
+ * // Update selection and repaint to show the visual change
1352
+ * tableApi.getSelectionModel().selectCell(2, 3);
1353
+ * tableApi.repaint();
1354
+ *
1355
+ * @example
1356
+ * // After changing column visibility, repaint to reflect changes
1357
+ * tableApi.setColumnVisible(0, false);
1358
+ * tableApi.repaint();
1359
+ *
1360
+ * @returns {void}
747
1361
  */
748
1362
  repaint() {
749
1363
  this.tableScope.repaint();
750
1364
  }
751
1365
  /**
752
- * Repaints the table scope with hard repaint.
753
- * Repaints the UI by resetting the size of the wrapper div,
754
- * adjusting the containers and rows, and performing additional adjustments
755
- * after scrolling.
1366
+ * Performs a complete repaint of the table by triggering a hard repaint on the underlying table scope.
756
1367
  *
757
- * @return {void}
1368
+ * A hard repaint is more thorough than a regular repaint and performs the following operations:
1369
+ * - Recalculates the height and padding of the table model
1370
+ * - Resets the size of the wrapper div elements
1371
+ * - Adjusts containers and rows positioning
1372
+ * - Makes additional adjustments after scrolling
1373
+ *
1374
+ * Use this method when regular repaint isn't sufficient, such as when:
1375
+ * - Table dimensions have significantly changed
1376
+ * - The structure of data has been modified (rows/columns added or removed)
1377
+ * - The table layout needs complete recalculation
1378
+ * - After major DOM changes affecting the table's container
1379
+ *
1380
+ * @example
1381
+ * // Example 1: Basic usage
1382
+ * tableApi.repaintHard();
1383
+ *
1384
+ * @example
1385
+ * // Example 2: Using after major data changes
1386
+ * tableApi.setRows(newDataSet);
1387
+ * tableApi.repaintHard();
1388
+ *
1389
+ * @example
1390
+ * // Example 3: Using after resizing a container
1391
+ * window.addEventListener('resize', () => {
1392
+ * tableApi.repaintHard();
1393
+ * });
1394
+ *
1395
+ * @example
1396
+ * // Example 4: Using after changing column visibility
1397
+ * tableApi.setColumnVisible(2, false);
1398
+ * tableApi.repaintHard();
1399
+ *
1400
+ * @returns {void} This method doesn't return a value
758
1401
  */
759
1402
  repaintHard() {
760
1403
  this.tableScope.repaintHard();
@@ -770,8 +1413,30 @@ class Xe {
770
1413
  this.tableScope.recalcColumnWidths(e);
771
1414
  }
772
1415
  /**
773
- * Clears the current selection of the table.
774
- * The table will be rendered automatically.
1416
+ * Clears the current selection in the table.
1417
+ *
1418
+ * This method removes any selected cells, rows, or columns in the table.
1419
+ * It provides a convenient way to programmatically clear all selections in the table
1420
+ * without having to access the underlying selection model directly.
1421
+ *
1422
+ * When called, this method delegates to the table scope's clearSelection method with
1423
+ * a parameter value of true, which ensures the table is automatically repainted after
1424
+ * the selection is cleared.
1425
+ *
1426
+ * @example
1427
+ * // Clear all selections in the table
1428
+ * tableApi.clearSelection();
1429
+ *
1430
+ * // Example usage in a component
1431
+ * class MyComponent {
1432
+ * @ViewChild('tableComponent') tableComponent: TableComponent;
1433
+ *
1434
+ * resetTableSelection(): void {
1435
+ * if (this.tableComponent?.api) {
1436
+ * this.tableComponent.api.clearSelection();
1437
+ * }
1438
+ * }
1439
+ * }
775
1440
  *
776
1441
  * @returns {void}
777
1442
  */
@@ -779,12 +1444,31 @@ class Xe {
779
1444
  this.tableScope.clearSelection(!0);
780
1445
  }
781
1446
  /**
782
- * Sets the selection model for the table scope.
1447
+ * Sets the selection model for the table.
783
1448
  *
784
- * @param {SelectionModel} sm - The selection model to be set.
785
- * @param {boolean} [repaint=true] - Indicates whether the table should be repainted after setting the selection model. Default value is true.
1449
+ * This method allows you to replace the current selection model with a new one,
1450
+ * which controls how cells, rows, or columns can be selected in the table.
786
1451
  *
787
- * @return {void}
1452
+ * @param {SelectionModel} sm - The new selection model to be set. This model defines
1453
+ * the selection behavior including selection type (none, cell, row, column),
1454
+ * selection mode (single, multi), and manages the selected ranges.
1455
+ * @param {boolean} [repaint=true] - Whether to repaint the table after changing the selection model.
1456
+ * Default is true, which immediately reflects the change visually.
1457
+ * Set to false if you want to avoid immediate repainting.
1458
+ *
1459
+ * @example
1460
+ * // Create a new selection model with row selection and multi-select mode
1461
+ * const selectionModel = new SelectionModel("row", "multi");
1462
+ *
1463
+ * // Set the new selection model and repaint the table
1464
+ * tableApi.setSelectionModel(selectionModel);
1465
+ *
1466
+ * // Set a selection model without repainting (if you plan to make more changes)
1467
+ * tableApi.setSelectionModel(selectionModel, false);
1468
+ * // ... make other changes ...
1469
+ * tableApi.repaint(); // Now repaint once
1470
+ *
1471
+ * @returns {void}
788
1472
  */
789
1473
  setSelectionModel(e, t = !0) {
790
1474
  this.tableScope.setSelectionModel(e, t);
@@ -800,9 +1484,36 @@ class Xe {
800
1484
  this.tableScope.onActionTriggered(e);
801
1485
  }
802
1486
  /**
803
- * Retrieves the mapping of shortcuts to corresponding action in the current table scope.
1487
+ * Retrieves the shortcut action mapping from the table's shortcut service.
1488
+ *
1489
+ * This method provides access to the keyboard shortcut configuration that defines
1490
+ * which keys trigger specific actions in the table. The mapping contains key-value
1491
+ * pairs where:
1492
+ * - Keys are string representations of keyboard shortcuts (e.g., "ctrl+c", "shift+arrow_down")
1493
+ * - Values are ActionId values representing the corresponding table actions
1494
+ *
1495
+ * This mapping can be useful for:
1496
+ * - Displaying available shortcuts to users
1497
+ * - Creating custom shortcut documentation
1498
+ * - Dynamically checking which actions are available via keyboard
1499
+ * - Extending or integrating with the table's shortcut system
1500
+ *
1501
+ * @returns {ShortcutActionIdMapping} An object mapping shortcut key combinations to their corresponding action IDs.
1502
+ * For example: { "ctrl+c": "COPY_2_CLIPBOARD", "arrow_down": "NAVIGATE_DOWN" }
1503
+ *
1504
+ * @example
1505
+ * // Get all available shortcuts in the table
1506
+ * const shortcuts = tableApi.getShortcutActionMapping();
804
1507
  *
805
- * @return {ShortcutActionIdMapping} The mapping of shortcuts to corresponding action.
1508
+ * // Check if a specific shortcut exists
1509
+ * if (shortcuts["ctrl+c"]) {
1510
+ * console.log("Copy shortcut is available with action:", shortcuts["ctrl+c"]);
1511
+ * }
1512
+ *
1513
+ * // Display available shortcuts in the UI
1514
+ * Object.entries(shortcuts).forEach(([key, actionId]) => {
1515
+ * console.log(`${key}: ${actionId}`);
1516
+ * });
806
1517
  */
807
1518
  getShortcutActionMapping() {
808
1519
  return this.tableScope.shortcutService.getShortcutActionMapping();
@@ -810,7 +1521,35 @@ class Xe {
810
1521
  /**
811
1522
  * Copies the selected data from the table to the clipboard.
812
1523
  *
813
- * @return {Promise<string>} - A promise that resolves with the copied data as a string.
1524
+ * This method leverages the copyService to extract and copy the currently selected data
1525
+ * from the table. It works with the current selection state and focus position to determine
1526
+ * what content should be copied.
1527
+ *
1528
+ * The copied data is formatted as tab-separated text that can be pasted into spreadsheet
1529
+ * applications like Excel or text editors while maintaining the tabular structure.
1530
+ *
1531
+ * @example
1532
+ * // Copy the currently selected data to clipboard
1533
+ * tableApi.copyToClipboard().then(content => {
1534
+ * console.log('Copied to clipboard:', content);
1535
+ * });
1536
+ *
1537
+ * // Using with a button click handler
1538
+ * function onCopyButtonClick() {
1539
+ * if (tableApi) {
1540
+ * tableApi.copyToClipboard()
1541
+ * .then(content => {
1542
+ * console.log('Successfully copied data to clipboard');
1543
+ * // Optionally do something with the copied content
1544
+ * })
1545
+ * .catch(error => {
1546
+ * console.error('Failed to copy to clipboard:', error);
1547
+ * });
1548
+ * }
1549
+ * }
1550
+ *
1551
+ * @returns {Promise<string>} A promise that resolves with the copied data as a string.
1552
+ * The string contains the tab-separated representation of the selected table data.
814
1553
  */
815
1554
  copyToClipboard() {
816
1555
  return this.tableScope.copyService.copyToClipboard(
@@ -820,11 +1559,33 @@ class Xe {
820
1559
  );
821
1560
  }
822
1561
  /**
823
- * Generates and downloads an Excel file based on the table data.
1562
+ * Downloads the current table data as an Excel file.
1563
+ *
1564
+ * This method extracts all visible data from the table (including header, body, and footer areas),
1565
+ * converts it into a matrix format, and triggers a download of an Excel file containing this data.
824
1566
  *
825
- * @param {string} fileName - The name of the Excel file to be downloaded. Defaults to 'table.xlsx'.
826
- * @param {string} author - The author of the Excel file. If not provided, it will remain empty.
827
- * @return {void} No return value. Initiates a file download of the Excel document.
1567
+ * The method works by:
1568
+ * 1. Creating an empty matrix to hold all table data
1569
+ * 2. Iterating through each area of the table (header, body, footer)
1570
+ * 3. For each area, iterating through all rows and columns to extract cell values
1571
+ * 4. Passing the complete data matrix to the Excel service for file generation and download
1572
+ *
1573
+ * @param {string} fileName - The name of the Excel file to be downloaded (default: 'table.xlsx')
1574
+ * @param {string} author - Optional metadata for the Excel file to specify the author (default: '')
1575
+ *
1576
+ * @returns {void} The result of the excelService.downloadExcel method call
1577
+ *
1578
+ * @example
1579
+ * // Download table data with default filename
1580
+ * tableApi.downloadExcel();
1581
+ *
1582
+ * @example
1583
+ * // Download table data with custom filename and author
1584
+ * tableApi.downloadExcel('sales-report.xlsx', 'John Doe');
1585
+ *
1586
+ * @example
1587
+ * // Download table data with custom filename only
1588
+ * tableApi.downloadExcel('quarterly-data.xlsx');
828
1589
  */
829
1590
  downloadExcel(e = "table.xlsx", t = "") {
830
1591
  const s = [], o = this.tableScope.tableModel.getColumnCount(), i = ["header", "body", "footer"];
@@ -840,18 +1601,66 @@ class Xe {
840
1601
  return this.tableScope.excelService.downloadExcel(s, e, t);
841
1602
  }
842
1603
  /**
843
- * Retrieves the current scope of the table.
1604
+ * Returns the TableScope instance associated with this TableApi.
1605
+ *
1606
+ * The TableScope provides access to the core functionality and internal state of the table component,
1607
+ * including rendering, event handling, selection, and other low-level operations.
1608
+ *
1609
+ * This method is useful for advanced customization scenarios where you need direct access
1610
+ * to the table's internal structure and behaviors.
1611
+ *
1612
+ * @returns {TableScope} The TableScope instance that controls this table component
844
1613
  *
845
- * @returns {TableScope} The current scope of the table.
1614
+ * @example
1615
+ * // Access the TableScope to perform a custom operation
1616
+ * const tableApi = new TableApi(myTableScope);
1617
+ * const tableScope = tableApi.getTableScope();
1618
+ *
1619
+ * // Example: Manually trigger a context menu at a specific location
1620
+ * const mouseEvent = new MouseEvent('contextmenu');
1621
+ * const geMouseEvent = tableScope.createGeMouseEvent(mouseEvent);
1622
+ * tableScope.contextmenu(geMouseEvent);
846
1623
  */
847
1624
  getTableScope() {
848
1625
  return this.tableScope;
849
1626
  }
850
1627
  /**
851
- * Retrieves the selection model of the table.
1628
+ * Returns the current selection model for the table.
1629
+ *
1630
+ * The selection model manages cell selection state, including single cells, ranges, rows, and columns.
1631
+ * This method provides access to the selection model instance, allowing operations like:
1632
+ * - Checking if cells are selected
1633
+ * - Getting selection ranges
1634
+ * - Modifying selections
1635
+ * - Adding/removing selection event listeners
1636
+ *
1637
+ * @returns {SelectionModelIf | undefined} The current selection model if available, otherwise undefined.
1638
+ *
1639
+ * @example
1640
+ * // Get the selection model
1641
+ * const selectionModel = tableApi.getSelectionModel();
1642
+ *
1643
+ * // Check if a specific cell is selected
1644
+ * if (selectionModel?.isSelected(3, 2)) {
1645
+ * console.log('Cell at row 3, column 2 is selected');
1646
+ * }
1647
+ *
1648
+ * // Get all selected ranges
1649
+ * const ranges = selectionModel?.getRanges();
1650
+ * console.log('Selected ranges:', ranges);
1651
+ *
1652
+ * // Clear all selections
1653
+ * selectionModel?.clear();
852
1654
  *
853
- * @return {SelectionModelIf | undefined} The selection model of the table,
854
- * or undefined if no selection model is available.
1655
+ * // Toggle selection of a cell
1656
+ * selectionModel?.togglePoint(5, 1);
1657
+ *
1658
+ * // Add a selection change listener
1659
+ * selectionModel?.addEventSelectionChangedListener({
1660
+ * selectionChanged: () => {
1661
+ * console.log('Selection has changed');
1662
+ * }
1663
+ * });
855
1664
  */
856
1665
  getSelectionModel() {
857
1666
  return this.tableScope.selectionModel();
@@ -1332,18 +2141,181 @@ class Xe {
1332
2141
  getFirstVisibleRowIndex() {
1333
2142
  return this.tableScope.getFirstVisibleRowIndex();
1334
2143
  }
2144
+ /**
2145
+ * Retrieves the index of the first fully visible row in the table's viewport.
2146
+ *
2147
+ * A row is considered "fully visible" when it's completely within the visible area of the table.
2148
+ * This differs from the regular "visible" row, which might be partially visible at the edges of the viewport.
2149
+ *
2150
+ * This method is useful for:
2151
+ * - Determining which rows are completely in view for operations that require full visibility
2152
+ * - Implementing pagination or virtualization logic that needs to know complete row visibility
2153
+ * - Supporting keyboard navigation that should skip partially visible rows
2154
+ *
2155
+ * @returns {number} The index of the first fully visible row, or -1 if no rows are fully visible
2156
+ *
2157
+ * @example
2158
+ * // Get the first fully visible row index
2159
+ * const firstFullVisibleRow = tableApi.getFirstFullVisibleRowIndex();
2160
+ *
2161
+ * // Check if a specific row is fully visible
2162
+ * const isRowFullyVisible = (rowIndex) => {
2163
+ * const firstFullVisible = tableApi.getFirstFullVisibleRowIndex();
2164
+ * const lastFullVisible = tableApi.getLastFullVisibleRowIndex();
2165
+ * return rowIndex >= firstFullVisible && rowIndex <= lastFullVisible;
2166
+ * };
2167
+ */
1335
2168
  getFirstFullVisibleRowIndex() {
1336
2169
  return this.tableScope.getFirstFullVisibleRowIndex();
1337
2170
  }
2171
+ /**
2172
+ * Returns the index of the last row that is visible in the table's viewport.
2173
+ *
2174
+ * This method retrieves the last visible row index from the table scope, which keeps
2175
+ * track of which rows are currently visible as the user scrolls through the table.
2176
+ *
2177
+ * This can be useful for:
2178
+ * - Implementing virtualized scrolling optimizations
2179
+ * - Determining if specific rows are currently in view
2180
+ * - Implementing features that need to know the visible range of rows
2181
+ *
2182
+ * @returns {number} The index of the last visible row in the table viewport
2183
+ *
2184
+ * @example
2185
+ * // Check if a specific row is currently visible in the viewport
2186
+ * const lastVisibleIndex = tableApi.getLastVisibleRowIndex();
2187
+ * const firstVisibleIndex = tableApi.getFirstVisibleRowIndex();
2188
+ * const isRowVisible = rowIndex >= firstVisibleIndex && rowIndex <= lastVisibleIndex;
2189
+ *
2190
+ * @example
2191
+ * // Get the range of visible rows
2192
+ * const visibleRowsRange = {
2193
+ * first: tableApi.getFirstVisibleRowIndex(),
2194
+ * last: tableApi.getLastVisibleRowIndex()
2195
+ * };
2196
+ * console.log(`Visible rows: ${visibleRowsRange.first} to ${visibleRowsRange.last}`);
2197
+ */
1338
2198
  getLastVisibleRowIndex() {
1339
2199
  return this.tableScope.getLastVisibleRowIndex();
1340
2200
  }
2201
+ /**
2202
+ * Returns the index of the last fully visible row in the table's viewport.
2203
+ *
2204
+ * This method retrieves the last row that is completely visible within the current
2205
+ * viewport of the table. A row is considered "fully visible" when its entire height
2206
+ * is visible without any portion being cut off by the viewport boundaries.
2207
+ *
2208
+ * The distinction between "visible" and "fully visible" is important when scrolling:
2209
+ * - A row can be partially visible (some portion is in view)
2210
+ * - A row can be fully visible (the entire row is in view)
2211
+ *
2212
+ * @returns {number} The index of the last fully visible row in the table.
2213
+ * If no row is fully visible or the table is empty, the method might return -1.
2214
+ *
2215
+ * @example
2216
+ * ```typescript
2217
+ * // Get the index of the last fully visible row
2218
+ * const lastVisibleRowIndex = tableApi.getLastFullVisibleRowIndex();
2219
+ *
2220
+ * // Use this information to determine if a specific row is fully visible
2221
+ * const isRowFullyVisible = rowIndex <= lastVisibleRowIndex && rowIndex >= tableApi.getFirstFullVisibleRowIndex();
2222
+ *
2223
+ * // Can be used with scrolling operations to ensure certain rows are visible
2224
+ * if (rowIndex > lastVisibleRowIndex) {
2225
+ * tableApi.ensureRowIsVisible(rowIndex);
2226
+ * }
2227
+ * ```
2228
+ */
1341
2229
  getLastFullVisibleRowIndex() {
1342
2230
  return this.tableScope.getLastFullVisibleRowIndex();
1343
2231
  }
2232
+ /**
2233
+ * Checks whether logging is currently active for the table component.
2234
+ *
2235
+ * This method returns the current state of logging for the table. When logging is active,
2236
+ * the table outputs detailed information about its operations to the console, including:
2237
+ *
2238
+ * - Rendering processes and lifecycle events
2239
+ * - Data modifications and updates
2240
+ * - Event handling and user interactions
2241
+ * - Performance metrics and state changes
2242
+ *
2243
+ * Logging can be toggled using the `setLoggingActive(boolean)` method.
2244
+ *
2245
+ * @returns {boolean} True if logging is currently enabled, false otherwise.
2246
+ *
2247
+ * @example
2248
+ * // Check if logging is enabled
2249
+ * if (tableApi.isLoggingActive()) {
2250
+ * console.log("Table logging is currently active");
2251
+ * }
2252
+ *
2253
+ * // Conditionally enable logging only if it's not already active
2254
+ * if (!tableApi.isLoggingActive()) {
2255
+ * tableApi.setLoggingActive(true);
2256
+ *
2257
+ * // Perform operations that need debugging
2258
+ * tableApi.updateCells([
2259
+ * {
2260
+ * area: "body",
2261
+ * rowIndex: 2,
2262
+ * columnIndex: 3,
2263
+ * value: "New Value",
2264
+ * cssClasses: { "highlight": true }
2265
+ * }
2266
+ * ]);
2267
+ *
2268
+ * // Run some additional operations...
2269
+ *
2270
+ * // Disable logging when finished
2271
+ * tableApi.setLoggingActive(false);
2272
+ * }
2273
+ */
1344
2274
  setLoggingActive(e) {
1345
2275
  this.tableScope.loggingActive = e;
1346
2276
  }
2277
+ /**
2278
+ * Checks whether logging is currently active for the table component.
2279
+ *
2280
+ * This method returns the current state of logging for the table. When logging is active,
2281
+ * the table outputs detailed information about its operations to the console, including:
2282
+ *
2283
+ * - Rendering processes and lifecycle events
2284
+ * - Data modifications and updates
2285
+ * - Event handling and user interactions
2286
+ * - Performance metrics and state changes
2287
+ *
2288
+ * Logging can be toggled using the `setLoggingActive(boolean)` method.
2289
+ *
2290
+ * @returns {boolean} True if logging is currently enabled, false otherwise.
2291
+ *
2292
+ * @example
2293
+ * // Check if logging is enabled
2294
+ * if (tableApi.isLoggingActive()) {
2295
+ * console.log("Table logging is currently active");
2296
+ * }
2297
+ *
2298
+ * // Conditionally enable logging only if it's not already active
2299
+ * if (!tableApi.isLoggingActive()) {
2300
+ * tableApi.setLoggingActive(true);
2301
+ *
2302
+ * // Perform operations that need debugging
2303
+ * tableApi.updateCells([
2304
+ * {
2305
+ * area: "body",
2306
+ * rowIndex: 2,
2307
+ * columnIndex: 3,
2308
+ * value: "New Value",
2309
+ * cssClasses: { "highlight": true }
2310
+ * }
2311
+ * ]);
2312
+ *
2313
+ * // Run some additional operations...
2314
+ *
2315
+ * // Disable logging when finished
2316
+ * tableApi.setLoggingActive(false);
2317
+ * }
2318
+ */
1347
2319
  isLoggingActive() {
1348
2320
  return this.tableScope.loggingActive;
1349
2321
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiexpert/preact-table",
3
- "version": "10.1.79",
3
+ "version": "10.1.81",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -8,7 +8,9 @@
8
8
  "entryFile": "src/index.ts"
9
9
  },
10
10
  "publishConfig": {
11
- "directory": "dist"
11
+ "directory": "dist",
12
+ "registry": "https://registry.npmjs.org/",
13
+ "access": "public"
12
14
  },
13
15
  "exports": {
14
16
  ".": {
@@ -19,7 +21,7 @@
19
21
  "dependencies": {
20
22
  "tslib": "^2.3.0",
21
23
  "preact": "^10.19.4",
22
- "@guiexpert/table": "^1.1.79"
24
+ "@guiexpert/table": "^1.1.81"
23
25
  },
24
26
  "devDependencies": {
25
27
  "react-scripts-ts": "^3.1.0",