@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.
- package/index.js +1013 -41
- 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
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
980
|
+
* Updates the cells in the table with the provided cell update events.
|
|
651
981
|
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
1064
|
+
* Notifies the table that an external filter has been changed and needs to be applied.
|
|
662
1065
|
*
|
|
663
|
-
*
|
|
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
|
|
1108
|
+
* Scrolls the table content to the specified pixel coordinates.
|
|
670
1109
|
*
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
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
|
|
1212
|
+
* Scrolls the table to display the specified row and column indices at the top-left corner of the viewport.
|
|
680
1213
|
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
746
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
774
|
-
*
|
|
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
|
|
1447
|
+
* Sets the selection model for the table.
|
|
783
1448
|
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
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
|
-
*
|
|
854
|
-
*
|
|
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.
|
|
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.
|
|
24
|
+
"@guiexpert/table": "^1.1.81"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
27
|
"react-scripts-ts": "^3.1.0",
|