@douyinfe/semi-foundation 2.97.0 → 2.98.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/codeHighlight/codeHighlight.scss +1 -1
- package/datePicker/foundation.ts +7 -0
- package/datePicker/inputFoundation.ts +5 -0
- package/form/foundation.ts +48 -4
- package/inputNumber/foundation.ts +119 -3
- package/jsonViewer/jsonViewer.scss +2 -2
- package/lib/cjs/aiChatInput/aiChatInput.css +7 -7
- package/lib/cjs/anchor/anchor.css +3 -3
- package/lib/cjs/autoComplete/autoComplete.css +1 -1
- package/lib/cjs/avatar/avatar.css +5 -5
- package/lib/cjs/badge/badge.css +1 -1
- package/lib/cjs/breadcrumb/breadcrumb.css +2 -2
- package/lib/cjs/calendar/calendar.css +9 -9
- package/lib/cjs/cascader/cascader.css +6 -6
- package/lib/cjs/checkbox/checkbox.css +2 -2
- package/lib/cjs/codeHighlight/codeHighlight.css +1 -1
- package/lib/cjs/codeHighlight/codeHighlight.scss +1 -1
- package/lib/cjs/collapse/collapse.css +2 -2
- package/lib/cjs/datePicker/datePicker.css +8 -8
- package/lib/cjs/datePicker/foundation.d.ts +5 -0
- package/lib/cjs/datePicker/foundation.js +2 -0
- package/lib/cjs/datePicker/inputFoundation.d.ts +5 -0
- package/lib/cjs/descriptions/descriptions.css +6 -6
- package/lib/cjs/dropdown/dropdown.css +2 -2
- package/lib/cjs/form/form.css +4 -4
- package/lib/cjs/form/foundation.js +49 -3
- package/lib/cjs/hotKeys/hotKeys.css +2 -2
- package/lib/cjs/image/image.css +2 -2
- package/lib/cjs/input/input.css +8 -8
- package/lib/cjs/input/textarea.css +2 -2
- package/lib/cjs/inputNumber/foundation.d.ts +15 -0
- package/lib/cjs/inputNumber/foundation.js +113 -3
- package/lib/cjs/jsonViewer/jsonViewer.css +2 -2
- package/lib/cjs/jsonViewer/jsonViewer.scss +2 -2
- package/lib/cjs/list/list.css +1 -1
- package/lib/cjs/modal/modal.css +1 -1
- package/lib/cjs/navigation/navigation.css +2 -2
- package/lib/cjs/notification/notification.css +4 -4
- package/lib/cjs/pagination/pagination.css +5 -5
- package/lib/cjs/popconfirm/popconfirm.css +1 -1
- package/lib/cjs/popover/popover.css +1 -1
- package/lib/cjs/radio/radio.css +2 -2
- package/lib/cjs/scrollList/itemFoundation.js +12 -0
- package/lib/cjs/scrollList/scrollList.css +2 -2
- package/lib/cjs/select/select.css +6 -6
- package/lib/cjs/sideSheet/sideSheet.css +2 -2
- package/lib/cjs/sidebar/sidebar.css +11 -11
- package/lib/cjs/slider/foundation.js +46 -12
- package/lib/cjs/slider/rtl.scss +62 -0
- package/lib/cjs/slider/slider.css +45 -0
- package/lib/cjs/slider/slider.scss +2 -0
- package/lib/cjs/steps/steps.css +11 -11
- package/lib/cjs/table/foundation.d.ts +36 -0
- package/lib/cjs/table/foundation.js +162 -28
- package/lib/cjs/table/table.css +10 -2
- package/lib/cjs/table/table.scss +17 -0
- package/lib/cjs/tabs/tabs.css +2 -2
- package/lib/cjs/tag/tag.css +2 -2
- package/lib/cjs/tagInput/tagInput.css +2 -2
- package/lib/cjs/timePicker/timePicker.css +1 -1
- package/lib/cjs/timeline/timeline.css +2 -2
- package/lib/cjs/toast/toast.css +1 -1
- package/lib/cjs/tooltip/foundation.js +8 -5
- package/lib/cjs/tooltip/tooltip.css +1 -1
- package/lib/cjs/transfer/constants.d.ts +3 -1
- package/lib/cjs/transfer/constants.js +3 -1
- package/lib/cjs/transfer/foundation.d.ts +3 -0
- package/lib/cjs/transfer/foundation.js +4 -0
- package/lib/cjs/transfer/transfer.css +14 -5
- package/lib/cjs/transfer/transfer.scss +10 -0
- package/lib/cjs/tree/foundation.d.ts +3 -0
- package/lib/cjs/tree/foundation.js +31 -4
- package/lib/cjs/tree/tree.css +1 -1
- package/lib/cjs/treeSelect/foundation.d.ts +1 -0
- package/lib/cjs/treeSelect/foundation.js +8 -1
- package/lib/cjs/treeSelect/treeSelect.css +36 -4
- package/lib/cjs/treeSelect/treeSelect.scss +49 -1
- package/lib/cjs/typography/typography.css +8 -8
- package/lib/cjs/upload/upload.css +8 -8
- package/lib/cjs/utils/Store.d.ts +1 -1
- package/lib/cjs/utils/Store.js +1 -0
- package/lib/es/aiChatInput/aiChatInput.css +7 -7
- package/lib/es/anchor/anchor.css +3 -3
- package/lib/es/autoComplete/autoComplete.css +1 -1
- package/lib/es/avatar/avatar.css +5 -5
- package/lib/es/badge/badge.css +1 -1
- package/lib/es/breadcrumb/breadcrumb.css +2 -2
- package/lib/es/calendar/calendar.css +9 -9
- package/lib/es/cascader/cascader.css +6 -6
- package/lib/es/checkbox/checkbox.css +2 -2
- package/lib/es/codeHighlight/codeHighlight.css +1 -1
- package/lib/es/codeHighlight/codeHighlight.scss +1 -1
- package/lib/es/collapse/collapse.css +2 -2
- package/lib/es/datePicker/datePicker.css +8 -8
- package/lib/es/datePicker/foundation.d.ts +5 -0
- package/lib/es/datePicker/foundation.js +2 -0
- package/lib/es/datePicker/inputFoundation.d.ts +5 -0
- package/lib/es/descriptions/descriptions.css +6 -6
- package/lib/es/dropdown/dropdown.css +2 -2
- package/lib/es/form/form.css +4 -4
- package/lib/es/form/foundation.js +49 -3
- package/lib/es/hotKeys/hotKeys.css +2 -2
- package/lib/es/image/image.css +2 -2
- package/lib/es/input/input.css +8 -8
- package/lib/es/input/textarea.css +2 -2
- package/lib/es/inputNumber/foundation.d.ts +15 -0
- package/lib/es/inputNumber/foundation.js +113 -3
- package/lib/es/jsonViewer/jsonViewer.css +2 -2
- package/lib/es/jsonViewer/jsonViewer.scss +2 -2
- package/lib/es/list/list.css +1 -1
- package/lib/es/modal/modal.css +1 -1
- package/lib/es/navigation/navigation.css +2 -2
- package/lib/es/notification/notification.css +4 -4
- package/lib/es/pagination/pagination.css +5 -5
- package/lib/es/popconfirm/popconfirm.css +1 -1
- package/lib/es/popover/popover.css +1 -1
- package/lib/es/radio/radio.css +2 -2
- package/lib/es/scrollList/itemFoundation.js +12 -0
- package/lib/es/scrollList/scrollList.css +2 -2
- package/lib/es/select/select.css +6 -6
- package/lib/es/sideSheet/sideSheet.css +2 -2
- package/lib/es/sidebar/sidebar.css +11 -11
- package/lib/es/slider/foundation.js +46 -12
- package/lib/es/slider/rtl.scss +62 -0
- package/lib/es/slider/slider.css +45 -0
- package/lib/es/slider/slider.scss +2 -0
- package/lib/es/steps/steps.css +11 -11
- package/lib/es/table/foundation.d.ts +36 -0
- package/lib/es/table/foundation.js +162 -28
- package/lib/es/table/table.css +10 -2
- package/lib/es/table/table.scss +17 -0
- package/lib/es/tabs/tabs.css +2 -2
- package/lib/es/tag/tag.css +2 -2
- package/lib/es/tagInput/tagInput.css +2 -2
- package/lib/es/timePicker/timePicker.css +1 -1
- package/lib/es/timeline/timeline.css +2 -2
- package/lib/es/toast/toast.css +1 -1
- package/lib/es/tooltip/foundation.js +8 -5
- package/lib/es/tooltip/tooltip.css +1 -1
- package/lib/es/transfer/constants.d.ts +3 -1
- package/lib/es/transfer/constants.js +3 -1
- package/lib/es/transfer/foundation.d.ts +3 -0
- package/lib/es/transfer/foundation.js +4 -0
- package/lib/es/transfer/transfer.css +14 -5
- package/lib/es/transfer/transfer.scss +10 -0
- package/lib/es/tree/foundation.d.ts +3 -0
- package/lib/es/tree/foundation.js +31 -4
- package/lib/es/tree/tree.css +1 -1
- package/lib/es/treeSelect/foundation.d.ts +1 -0
- package/lib/es/treeSelect/foundation.js +8 -1
- package/lib/es/treeSelect/treeSelect.css +36 -4
- package/lib/es/treeSelect/treeSelect.scss +49 -1
- package/lib/es/typography/typography.css +8 -8
- package/lib/es/upload/upload.css +8 -8
- package/lib/es/utils/Store.d.ts +1 -1
- package/lib/es/utils/Store.js +1 -0
- package/package.json +19 -4
- package/scrollList/itemFoundation.ts +12 -0
- package/slider/foundation.ts +55 -15
- package/slider/rtl.scss +62 -0
- package/slider/slider.scss +2 -0
- package/table/foundation.ts +197 -29
- package/table/table.scss +17 -0
- package/tooltip/foundation.ts +8 -5
- package/transfer/constants.ts +3 -1
- package/transfer/foundation.ts +8 -1
- package/transfer/transfer.scss +10 -0
- package/tree/foundation.ts +34 -5
- package/treeSelect/foundation.ts +10 -1
- package/treeSelect/treeSelect.scss +49 -1
- package/utils/Store.ts +2 -1
package/slider/rtl.scss
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
$module: #{$prefix}-slider;
|
|
2
|
+
|
|
3
|
+
// RTL support (horizontal)
|
|
4
|
+
// Slider uses `left` positioning in LTR. In RTL we switch to `right` positioning
|
|
5
|
+
// in the component logic, so centering transforms must be mirrored.
|
|
6
|
+
.#{$prefix}-rtl,
|
|
7
|
+
.#{$prefix}-portal-rtl {
|
|
8
|
+
.#{$module} {
|
|
9
|
+
direction: rtl;
|
|
10
|
+
|
|
11
|
+
&-handle {
|
|
12
|
+
transform: $transform_scale-slider_handle translateX(50%) translateY($spacing-slider_handle-translateY);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&-mark {
|
|
16
|
+
transform: translate(50%, 0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&-mark-reverse {
|
|
20
|
+
transform: translate(50%, 0) rotate(-180deg);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Boundary text should match RTL direction: min on the right, max on the left
|
|
24
|
+
|
|
25
|
+
&-boundary-min {
|
|
26
|
+
left: auto;
|
|
27
|
+
right: $spacing-slider_boundary_min-left;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&-boundary-max {
|
|
31
|
+
right: auto;
|
|
32
|
+
left: $spacing-slider_boundary_max-right;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Backward/explicit support: the component may add `semi-slider-rtl` on wrapper.
|
|
38
|
+
// Keep these rules so RTL transforms still apply even without `.semi-rtl` container.
|
|
39
|
+
|
|
40
|
+
.#{$module}-rtl {
|
|
41
|
+
.#{$module}-handle {
|
|
42
|
+
transform: $transform_scale-slider_handle translateX(50%) translateY($spacing-slider_handle-translateY);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.#{$module}-mark {
|
|
46
|
+
transform: translate(50%, 0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.#{$module}-mark-reverse {
|
|
50
|
+
transform: translate(50%, 0) rotate(-180deg);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.#{$module}-boundary-min {
|
|
54
|
+
left: auto;
|
|
55
|
+
right: $spacing-slider_boundary_min-left;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.#{$module}-boundary-max {
|
|
59
|
+
right: auto;
|
|
60
|
+
left: $spacing-slider_boundary_max-right;
|
|
61
|
+
}
|
|
62
|
+
}
|
package/slider/slider.scss
CHANGED
package/table/foundation.ts
CHANGED
|
@@ -21,6 +21,13 @@ import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
|
21
21
|
import { strings, numbers } from './constants';
|
|
22
22
|
import { mergeQueries, flattenColumns, filterColumns } from './utils';
|
|
23
23
|
import { pullAll, withOrderSort } from '../utils/array';
|
|
24
|
+
import {
|
|
25
|
+
convertDataToEntities,
|
|
26
|
+
calcCheckedKeys,
|
|
27
|
+
calcCheckedKeysForChecked,
|
|
28
|
+
calcCheckedKeysForUnchecked,
|
|
29
|
+
findDescendantKeys,
|
|
30
|
+
} from '../tree/treeUtil';
|
|
24
31
|
|
|
25
32
|
export interface BaseColumnProps<RecordType> {
|
|
26
33
|
align?: BaseAlign;
|
|
@@ -78,8 +85,11 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
|
|
|
78
85
|
setFlattenData: (flattenData: RecordType[]) => void;
|
|
79
86
|
setAllRowKeys: (allRowKeys: BaseRowKeyType[]) => void;
|
|
80
87
|
setHoveredRowKey: (hoveredRowKey: BaseRowKeyType) => void;
|
|
88
|
+
setHoveredRowKeys: (hoveredRowKeys: BaseRowKeyType[]) => void;
|
|
81
89
|
setCachedFilteredSortedDataSource: (filteredSortedDataSource: RecordType[]) => void;
|
|
82
90
|
setCachedFilteredSortedRowKeys: (filteredSortedRowKeys: BaseRowKeyType[]) => void;
|
|
91
|
+
setHalfCheckedRowKeys: (halfCheckedRowKeys: BaseRowKeyType[]) => void;
|
|
92
|
+
setKeyEntities: (keyEntities: BaseEntitys) => void;
|
|
83
93
|
getCurrentPage: () => number;
|
|
84
94
|
getCurrentPageSize: () => number;
|
|
85
95
|
getCachedFilteredSortedDataSource: () => RecordType[];
|
|
@@ -88,6 +98,9 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
|
|
|
88
98
|
setAllDisabledRowKeys: (allDisabledRowKeys: BaseRowKeyType[]) => void;
|
|
89
99
|
getAllDisabledRowKeys: () => BaseRowKeyType[];
|
|
90
100
|
getAllDisabledRowKeysSet: () => Set<BaseRowKeyType>;
|
|
101
|
+
getHalfCheckedRowKeys: () => BaseRowKeyType[];
|
|
102
|
+
getHalfCheckedRowKeysSet: () => Set<BaseRowKeyType>;
|
|
103
|
+
getKeyEntities: () => BaseEntitys;
|
|
91
104
|
notifyFilterDropdownVisibleChange: (visible: boolean, dataIndex: string) => void;
|
|
92
105
|
notifyChange: (changeInfo: { pagination: BasePagination; filters: BaseChangeInfoFilter<RecordType>[]; sorter: BaseChangeInfoSorter<RecordType>; extra: OnChangeExtra }) => void;
|
|
93
106
|
notifyExpand: (expanded?: boolean, record?: BaseIncludeGroupRecord<RecordType>, mouseEvent?: any) => void;
|
|
@@ -107,7 +120,8 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
|
|
|
107
120
|
getHandleColumns: () => (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[];
|
|
108
121
|
getMergePagination: () => (pagination: BasePagination) => BasePagination;
|
|
109
122
|
setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void;
|
|
110
|
-
getTableLayout: () => 'fixed' | 'auto'
|
|
123
|
+
getTableLayout: () => 'fixed' | 'auto';
|
|
124
|
+
getCheckRelation: () => CheckRelation
|
|
111
125
|
}
|
|
112
126
|
|
|
113
127
|
class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
|
|
@@ -756,30 +770,118 @@ class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType
|
|
|
756
770
|
return !(Array.isArray(dataSource) && dataSource.length > 0);
|
|
757
771
|
}
|
|
758
772
|
|
|
773
|
+
/**
|
|
774
|
+
* Build tree data entities for checkRelation
|
|
775
|
+
* @param dataSource
|
|
776
|
+
* @returns keyEntities map
|
|
777
|
+
*/
|
|
778
|
+
buildKeyEntities(dataSource?: RecordType[]): BaseEntitys {
|
|
779
|
+
dataSource = dataSource == null ? this._getDataSource() : dataSource;
|
|
780
|
+
const childrenRecordName = this.getProp('childrenRecordName');
|
|
781
|
+
const rowKey = this.getProp('rowKey');
|
|
782
|
+
|
|
783
|
+
// Convert table data to tree data format
|
|
784
|
+
const convertToTreeData = (data: RecordType[]): any[] => {
|
|
785
|
+
return data.map(record => {
|
|
786
|
+
const key = typeof rowKey === 'function' ? rowKey(record) : get(record, rowKey);
|
|
787
|
+
const children = get(record, childrenRecordName);
|
|
788
|
+
const node: any = { key, ...record };
|
|
789
|
+
if (Array.isArray(children) && children.length) {
|
|
790
|
+
node.children = convertToTreeData(children);
|
|
791
|
+
}
|
|
792
|
+
return node;
|
|
793
|
+
});
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
const treeData = convertToTreeData(dataSource);
|
|
797
|
+
const { keyEntities } = convertDataToEntities(treeData, { key: 'key', children: 'children' });
|
|
798
|
+
return keyEntities;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Calculate checked keys when checkRelation is 'related'
|
|
803
|
+
* @param realKey
|
|
804
|
+
* @param selected
|
|
805
|
+
* @param checkedKeys
|
|
806
|
+
* @param halfCheckedKeys
|
|
807
|
+
*/
|
|
808
|
+
calcCheckedKeysForSelect(realKey: BaseRowKeyType, selected: boolean, checkedKeys: Set<string>, halfCheckedKeys: Set<string>) {
|
|
809
|
+
const keyEntities = this._adapter.getKeyEntities();
|
|
810
|
+
const keyStr = String(realKey);
|
|
811
|
+
|
|
812
|
+
// If keyEntities doesn't contain this key, handle it as a simple add/remove
|
|
813
|
+
if (!keyEntities || !keyEntities[keyStr]) {
|
|
814
|
+
if (selected) {
|
|
815
|
+
checkedKeys.add(keyStr);
|
|
816
|
+
} else {
|
|
817
|
+
checkedKeys.delete(keyStr);
|
|
818
|
+
}
|
|
819
|
+
return { checkedKeys, halfCheckedKeys };
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
if (selected) {
|
|
823
|
+
return calcCheckedKeysForChecked(keyStr, keyEntities, checkedKeys, halfCheckedKeys);
|
|
824
|
+
} else {
|
|
825
|
+
return calcCheckedKeysForUnchecked(keyStr, keyEntities, checkedKeys, halfCheckedKeys);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
759
829
|
handleSelectRow(realKey: BaseRowKeyType, selected: boolean, e: any) {
|
|
760
830
|
this.stopPropagation(e);
|
|
761
831
|
if (typeof selected === 'boolean' && realKey != null) {
|
|
832
|
+
const checkRelation = this._adapter.getCheckRelation();
|
|
762
833
|
const selectedRowKeys = this._getSelectedRowKeys();
|
|
834
|
+
const halfCheckedRowKeys = [...(this._adapter.getHalfCheckedRowKeys() || [])];
|
|
763
835
|
let foundIdx = -1;
|
|
764
836
|
const selectedRow = this.getSelectedRows(null, [realKey])[0];
|
|
765
837
|
let selectedRows: BaseIncludeGroupRecord<RecordType>[];
|
|
766
838
|
|
|
767
|
-
if (
|
|
768
|
-
|
|
769
|
-
|
|
839
|
+
if (checkRelation === 'related') {
|
|
840
|
+
// When checkRelation is 'related', use tree selection logic
|
|
841
|
+
const keyEntities = this._adapter.getKeyEntities();
|
|
842
|
+
// Convert keys to strings for tree utility functions
|
|
843
|
+
const checkedKeysSet = new Set(selectedRowKeys.map(key => String(key)));
|
|
844
|
+
const halfCheckedKeysSet = new Set(halfCheckedRowKeys.map(key => String(key)));
|
|
845
|
+
|
|
846
|
+
const { checkedKeys, halfCheckedKeys } = this.calcCheckedKeysForSelect(
|
|
847
|
+
String(realKey),
|
|
848
|
+
selected,
|
|
849
|
+
checkedKeysSet,
|
|
850
|
+
halfCheckedKeysSet
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
const newSelectedRowKeys = [...checkedKeys];
|
|
854
|
+
const newHalfCheckedRowKeys = [...halfCheckedKeys];
|
|
855
|
+
selectedRows = this.getSelectedRows(null, newSelectedRowKeys);
|
|
856
|
+
|
|
857
|
+
// Always update halfCheckedRowKeys state for checkRelation='related' mode
|
|
858
|
+
// This is needed for rendering the half-checked state in the UI
|
|
859
|
+
this._adapter.setHalfCheckedRowKeys(newHalfCheckedRowKeys);
|
|
860
|
+
|
|
770
861
|
if (!this._selectionIsControlled()) {
|
|
771
|
-
this._adapter.setSelectedRowKeys(
|
|
862
|
+
this._adapter.setSelectedRowKeys(newSelectedRowKeys);
|
|
772
863
|
}
|
|
773
864
|
this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
|
|
774
|
-
this._adapter.notifySelectionChange(
|
|
775
|
-
} else
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
this.
|
|
865
|
+
this._adapter.notifySelectionChange(newSelectedRowKeys, selectedRows);
|
|
866
|
+
} else {
|
|
867
|
+
// Original logic for unRelated mode
|
|
868
|
+
if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
|
|
869
|
+
selectedRowKeys.splice(foundIdx, 1);
|
|
870
|
+
selectedRows = this.getSelectedRows(null, selectedRowKeys);
|
|
871
|
+
if (!this._selectionIsControlled()) {
|
|
872
|
+
this._adapter.setSelectedRowKeys(selectedRowKeys);
|
|
873
|
+
}
|
|
874
|
+
this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
|
|
875
|
+
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
876
|
+
} else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
|
|
877
|
+
selectedRowKeys.push(realKey);
|
|
878
|
+
selectedRows = this.getSelectedRows(null, selectedRowKeys);
|
|
879
|
+
if (!this._selectionIsControlled()) {
|
|
880
|
+
this._adapter.setSelectedRowKeys(selectedRowKeys);
|
|
881
|
+
}
|
|
882
|
+
this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
|
|
883
|
+
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
780
884
|
}
|
|
781
|
-
this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
|
|
782
|
-
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
783
885
|
}
|
|
784
886
|
}
|
|
785
887
|
}
|
|
@@ -792,6 +894,7 @@ class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType
|
|
|
792
894
|
handleSelectAllRow(selected: boolean, e: any) {
|
|
793
895
|
this.stopPropagation(e);
|
|
794
896
|
if (typeof selected === 'boolean') {
|
|
897
|
+
const checkRelation = this._adapter.getCheckRelation();
|
|
795
898
|
const curSelectedRowKeys = this._getSelectedRowKeys();
|
|
796
899
|
let selectedRowKeys = [...curSelectedRowKeys];
|
|
797
900
|
const selectedRowKeysSet = this._getSelectedRowKeysSet();
|
|
@@ -800,28 +903,78 @@ class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType
|
|
|
800
903
|
const disabledRowKeysSet = this._adapter.getAllDisabledRowKeysSet();
|
|
801
904
|
let changedRowKeys;
|
|
802
905
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
906
|
+
if (checkRelation === 'related') {
|
|
907
|
+
// When checkRelation is 'related', use tree selection logic
|
|
908
|
+
const keyEntities = this._adapter.getKeyEntities();
|
|
909
|
+
const halfCheckedRowKeys = [...(this._adapter.getHalfCheckedRowKeys() || [])];
|
|
910
|
+
// Convert keys to strings for tree utility functions
|
|
911
|
+
let checkedKeysSet = new Set(selectedRowKeys.map(key => String(key)));
|
|
912
|
+
let halfCheckedKeysSet = new Set(halfCheckedRowKeys.map(key => String(key)));
|
|
913
|
+
|
|
914
|
+
if (selected) {
|
|
915
|
+
// Select all: add all non-disabled keys
|
|
916
|
+
const keysToAdd = allRowKeys.filter(key => !disabledRowKeysSet.has(key));
|
|
917
|
+
for (const key of keysToAdd) {
|
|
918
|
+
const keyStr = String(key);
|
|
919
|
+
if (!checkedKeysSet.has(keyStr) && keyEntities && keyEntities[keyStr]) {
|
|
920
|
+
const result = calcCheckedKeysForChecked(keyStr, keyEntities, checkedKeysSet, halfCheckedKeysSet);
|
|
921
|
+
checkedKeysSet = result.checkedKeys;
|
|
922
|
+
halfCheckedKeysSet = result.halfCheckedKeys;
|
|
923
|
+
}
|
|
808
924
|
}
|
|
925
|
+
changedRowKeys = keysToAdd;
|
|
926
|
+
} else {
|
|
927
|
+
// Deselect all: remove all keys
|
|
928
|
+
const keysToRemove = [...checkedKeysSet];
|
|
929
|
+
for (const key of keysToRemove) {
|
|
930
|
+
if (keyEntities && keyEntities[key]) {
|
|
931
|
+
const result = calcCheckedKeysForUnchecked(key, keyEntities, checkedKeysSet, halfCheckedKeysSet);
|
|
932
|
+
checkedKeysSet = result.checkedKeys;
|
|
933
|
+
halfCheckedKeysSet = result.halfCheckedKeys;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
changedRowKeys = [...curSelectedRowKeys];
|
|
809
937
|
}
|
|
810
|
-
|
|
811
|
-
|
|
938
|
+
|
|
939
|
+
selectedRowKeys = [...checkedKeysSet];
|
|
940
|
+
const newHalfCheckedRowKeys = [...halfCheckedKeysSet];
|
|
941
|
+
const changedRows = this.getSelectedRows(null, changedRowKeys || []);
|
|
942
|
+
const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
|
|
943
|
+
|
|
944
|
+
// Always update halfCheckedRowKeys state for checkRelation='related' mode
|
|
945
|
+
// This is needed for rendering the half-checked state in the UI
|
|
946
|
+
this._adapter.setHalfCheckedRowKeys(newHalfCheckedRowKeys);
|
|
947
|
+
|
|
948
|
+
if (!this._selectionIsControlled()) {
|
|
949
|
+
this._adapter.setSelectedRowKeys(selectedRowKeys);
|
|
950
|
+
}
|
|
951
|
+
this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
|
|
952
|
+
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
812
953
|
} else {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
954
|
+
// Original logic for unRelated mode
|
|
955
|
+
// Select all, if not disabled && not in selectedRowKeys
|
|
956
|
+
if (selected) {
|
|
957
|
+
for (const key of allRowKeys) {
|
|
958
|
+
if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
|
|
959
|
+
selectedRowKeys.push(key);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
|
|
963
|
+
changedRowKeys = [...allRowKeys];
|
|
964
|
+
} else {
|
|
965
|
+
selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
|
|
966
|
+
changedRowKeys = [...curSelectedRowKeys];
|
|
967
|
+
}
|
|
816
968
|
|
|
817
|
-
|
|
818
|
-
|
|
969
|
+
const changedRows = this.getSelectedRows(null, changedRowKeys || []);
|
|
970
|
+
const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
|
|
819
971
|
|
|
820
|
-
|
|
821
|
-
|
|
972
|
+
if (!this._selectionIsControlled()) {
|
|
973
|
+
this._adapter.setSelectedRowKeys(selectedRowKeys);
|
|
974
|
+
}
|
|
975
|
+
this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
|
|
976
|
+
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
822
977
|
}
|
|
823
|
-
this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
|
|
824
|
-
this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
|
|
825
978
|
}
|
|
826
979
|
}
|
|
827
980
|
|
|
@@ -1283,4 +1436,19 @@ export type BaseIncludeGroupRecord<RecordType> = RecordType | { groupKey: string
|
|
|
1283
1436
|
|
|
1284
1437
|
export type BaseEllipsis = boolean | { showTitle: boolean };
|
|
1285
1438
|
|
|
1439
|
+
export type CheckRelation = 'related' | 'unRelated';
|
|
1440
|
+
|
|
1441
|
+
export interface BaseEntity {
|
|
1442
|
+
key?: string | number;
|
|
1443
|
+
level?: number;
|
|
1444
|
+
children?: BaseEntity[];
|
|
1445
|
+
parent?: BaseEntity | null;
|
|
1446
|
+
data?: Record<string, any>;
|
|
1447
|
+
[key: string]: any
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
export interface BaseEntitys {
|
|
1451
|
+
[key: string]: BaseEntity
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1286
1454
|
export default TableFoundation;
|
package/table/table.scss
CHANGED
|
@@ -259,6 +259,23 @@ $module: #{$prefix}-table;
|
|
|
259
259
|
display: table-row;
|
|
260
260
|
background-color: $color-table_body-bg-default;
|
|
261
261
|
|
|
262
|
+
// Programmatic hover state (e.g. rowSpanHover feature)
|
|
263
|
+
// Keep visual effect consistent with native :hover
|
|
264
|
+
&.#{$module}-row-hovered {
|
|
265
|
+
& > .#{$module}-row-cell {
|
|
266
|
+
background-image: linear-gradient(0deg, $color-table_body-bg-hover, $color-table_body-bg-hover);
|
|
267
|
+
background-color: $color-table_cell-bg-hover;
|
|
268
|
+
|
|
269
|
+
&.#{$module}-cell-fixed {
|
|
270
|
+
&-left,
|
|
271
|
+
&-right {
|
|
272
|
+
background-image: linear-gradient(0deg, $color-table_body-bg-hover, $color-table_body-bg-hover);
|
|
273
|
+
background-color: $color-table_body-bg-default;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
262
279
|
&:hover {
|
|
263
280
|
& > .#{$module}-row-cell {
|
|
264
281
|
// $color-table_body-bg-hover has transparency,will reveal the background color $color-table_body-bg-default\
|
package/tooltip/foundation.ts
CHANGED
|
@@ -210,7 +210,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
210
210
|
switch (types) {
|
|
211
211
|
case 'focus':
|
|
212
212
|
triggerEventSet[eventNames.focus] = () => {
|
|
213
|
-
this.delayShow();
|
|
213
|
+
this.getProp('condition') !== false && this.delayShow();
|
|
214
214
|
};
|
|
215
215
|
triggerEventSet[eventNames.blur] = () => {
|
|
216
216
|
this.delayHide();
|
|
@@ -220,7 +220,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
220
220
|
case 'click':
|
|
221
221
|
triggerEventSet[eventNames.click] = () => {
|
|
222
222
|
// this.delayShow();
|
|
223
|
-
this.show();
|
|
223
|
+
this.getProp('condition') !== false && this.show();
|
|
224
224
|
};
|
|
225
225
|
portalEventSet = {};
|
|
226
226
|
// Click outside needs special treatment, can not be directly tied to the trigger Element, need to be bound to the document
|
|
@@ -229,7 +229,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
229
229
|
triggerEventSet[eventNames.mouseEnter] = () => {
|
|
230
230
|
// console.log(e);
|
|
231
231
|
this.setCache('isClickToHide', false);
|
|
232
|
-
this.delayShow();
|
|
232
|
+
this.getProp('condition') !== false && this.delayShow();
|
|
233
233
|
// this.show('trigger');
|
|
234
234
|
};
|
|
235
235
|
triggerEventSet[eventNames.mouseLeave] = () => {
|
|
@@ -240,7 +240,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
240
240
|
// bind focus to hover trigger for a11y
|
|
241
241
|
triggerEventSet[eventNames.focus] = () => {
|
|
242
242
|
const { disableFocusListener } = this.getProps();
|
|
243
|
-
!disableFocusListener && this.delayShow();
|
|
243
|
+
this.getProp('condition') !== false && !disableFocusListener && this.delayShow();
|
|
244
244
|
};
|
|
245
245
|
triggerEventSet[eventNames.blur] = () => {
|
|
246
246
|
const { disableFocusListener } = this.getProps();
|
|
@@ -259,7 +259,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
259
259
|
return;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
this.delayShow();
|
|
262
|
+
this.getProp('condition') !== false && this.delayShow();
|
|
263
263
|
};
|
|
264
264
|
}
|
|
265
265
|
break;
|
|
@@ -269,6 +269,9 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
269
269
|
break;
|
|
270
270
|
case 'contextMenu':
|
|
271
271
|
triggerEventSet[eventNames.contextMenu] = (e) => {
|
|
272
|
+
if (this.getProp('condition') === false) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
272
275
|
e.preventDefault();
|
|
273
276
|
this.show();
|
|
274
277
|
};
|
package/transfer/constants.ts
CHANGED
package/transfer/foundation.ts
CHANGED
|
@@ -40,7 +40,9 @@ export interface TransferAdapter<P = Record<string, any>, S = Record<string, any
|
|
|
40
40
|
notifyDeselect: (items: BasicDataItem) => void;
|
|
41
41
|
updateInput: (input: string) => void;
|
|
42
42
|
updateSearchResult: (searchResult: Set<number | string>) => void;
|
|
43
|
-
searchTree: (keyword: string) => void
|
|
43
|
+
searchTree: (keyword: string) => void;
|
|
44
|
+
updateCurrentPage: (currentPage: number) => void;
|
|
45
|
+
notifyPageChange: (currentPage: number) => void;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
export default class TransferFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<TransferAdapter<P, S>> {
|
|
@@ -253,4 +255,9 @@ export default class TransferFoundation<P = Record<string, any>, S = Record<stri
|
|
|
253
255
|
this._notifyChange(newSelectedItems);
|
|
254
256
|
}
|
|
255
257
|
|
|
258
|
+
handlePageChange(currentPage: number) {
|
|
259
|
+
this._adapter.updateCurrentPage(currentPage);
|
|
260
|
+
this._adapter.notifyPageChange(currentPage);
|
|
261
|
+
}
|
|
262
|
+
|
|
256
263
|
}
|
package/transfer/transfer.scss
CHANGED
|
@@ -118,6 +118,16 @@ $module: #{$prefix}-transfer;
|
|
|
118
118
|
flex-grow: 1;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
&-pagination {
|
|
122
|
+
padding-top: $spacing-base-tight;
|
|
123
|
+
padding-bottom: $spacing-base-tight;
|
|
124
|
+
padding-left: $spacing-base-tight;
|
|
125
|
+
padding-right: $spacing-base-tight;
|
|
126
|
+
flex-shrink: 0;
|
|
127
|
+
display: flex;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
}
|
|
130
|
+
|
|
121
131
|
&-empty {
|
|
122
132
|
height: $height-transfer_left_empty;
|
|
123
133
|
}
|
package/tree/foundation.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* https://github.com/react-component/tree
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { isUndefined, difference, pick, get } from 'lodash';
|
|
6
|
+
import { isUndefined, difference, pick, get, throttle } from 'lodash';
|
|
7
7
|
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
8
8
|
import {
|
|
9
9
|
flattenTreeData,
|
|
@@ -322,11 +322,35 @@ export interface TreeAdapter extends DefaultAdapter<BasicTreeProps, BasicTreeInn
|
|
|
322
322
|
|
|
323
323
|
export default class TreeFoundation extends BaseFoundation<TreeAdapter, BasicTreeProps, BasicTreeInnerData> {
|
|
324
324
|
delayedDragEnterLogic: any;
|
|
325
|
+
throttledDragOverUpdate: ReturnType<typeof throttle>;
|
|
325
326
|
|
|
326
327
|
constructor(adapter: TreeAdapter) {
|
|
327
328
|
super({
|
|
328
329
|
...adapter,
|
|
329
330
|
});
|
|
331
|
+
// Throttle drag over state updates to improve performance during fast dragging
|
|
332
|
+
// 16ms ≈ 60fps, ensuring smooth updates without excessive re-renders
|
|
333
|
+
this.throttledDragOverUpdate = throttle((dropPosition: number) => {
|
|
334
|
+
this._adapter.updateState({
|
|
335
|
+
dropPosition,
|
|
336
|
+
});
|
|
337
|
+
}, 16);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
destroy() {
|
|
341
|
+
super.destroy();
|
|
342
|
+
// Cancel any pending throttled updates
|
|
343
|
+
if (this.throttledDragOverUpdate) {
|
|
344
|
+
this.throttledDragOverUpdate.cancel();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Clear pending delayed drag enter timers to avoid updates after unmount
|
|
348
|
+
if (this.delayedDragEnterLogic) {
|
|
349
|
+
Object.keys(this.delayedDragEnterLogic).forEach(key => {
|
|
350
|
+
clearTimeout(this.delayedDragEnterLogic[key]);
|
|
351
|
+
});
|
|
352
|
+
this.delayedDragEnterLogic = null;
|
|
353
|
+
}
|
|
330
354
|
}
|
|
331
355
|
|
|
332
356
|
_isMultiple() {
|
|
@@ -863,21 +887,22 @@ export default class TreeFoundation extends BaseFoundation<TreeAdapter, BasicTre
|
|
|
863
887
|
return;
|
|
864
888
|
}
|
|
865
889
|
|
|
866
|
-
// Update the drag position
|
|
890
|
+
// Update the drag position with throttle to improve performance
|
|
867
891
|
if (dragNode && eventKey === dragOverNodeKey) {
|
|
868
892
|
const newPos = calcDropRelativePosition(e, treeNode);
|
|
869
893
|
if (dropPosition === newPos) {
|
|
870
894
|
return;
|
|
871
895
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
});
|
|
896
|
+
// Use throttled update to reduce re-renders during fast dragging
|
|
897
|
+
this.throttledDragOverUpdate(newPos);
|
|
875
898
|
}
|
|
876
899
|
|
|
877
900
|
this.triggerDragEvent('onDragOver', e, treeNode);
|
|
878
901
|
}
|
|
879
902
|
|
|
880
903
|
handleNodeDragLeave(e: any, treeNode: BasicTreeNodeData) {
|
|
904
|
+
// Cancel pending throttled updates when leaving a node
|
|
905
|
+
this.throttledDragOverUpdate.cancel();
|
|
881
906
|
this._adapter.updateState({
|
|
882
907
|
dragOverNodeKey: '',
|
|
883
908
|
});
|
|
@@ -885,12 +910,16 @@ export default class TreeFoundation extends BaseFoundation<TreeAdapter, BasicTre
|
|
|
885
910
|
}
|
|
886
911
|
|
|
887
912
|
handleNodeDragEnd(e: any, treeNode: BasicTreeNodeData) {
|
|
913
|
+
// Flush any pending throttled updates before clearing drag state
|
|
914
|
+
this.throttledDragOverUpdate.flush();
|
|
888
915
|
this.clearDragState();
|
|
889
916
|
this.triggerDragEvent('onDragEnd', e, treeNode);
|
|
890
917
|
this._adapter.setDragNode(null);
|
|
891
918
|
}
|
|
892
919
|
|
|
893
920
|
handleNodeDrop(e: any, treeNode: BasicTreeNodeData, dragNode: any) {
|
|
921
|
+
// Flush any pending throttled updates to ensure accurate drop position
|
|
922
|
+
this.throttledDragOverUpdate.flush();
|
|
894
923
|
const { dropPosition, dragNodesKeys } = this.getStates();
|
|
895
924
|
const { eventKey, pos } = treeNode;
|
|
896
925
|
this.clearDragState();
|
package/treeSelect/foundation.ts
CHANGED
|
@@ -119,6 +119,7 @@ export interface BasicTreeSelectProps extends Pick<BasicTreeProps,
|
|
|
119
119
|
outerTopSlot?: any;
|
|
120
120
|
placeholder?: string;
|
|
121
121
|
prefix?: any;
|
|
122
|
+
remote?: boolean;
|
|
122
123
|
searchAutoFocus?: boolean;
|
|
123
124
|
searchPlaceholder?: string;
|
|
124
125
|
showSearchClear?: boolean;
|
|
@@ -626,7 +627,15 @@ export default class TreeSelectFoundation<P = Record<string, any>, S = Record<st
|
|
|
626
627
|
// Input is used as controlled component
|
|
627
628
|
this._adapter.updateInputValue(sugInput);
|
|
628
629
|
const { flattenNodes, expandedKeys, selectedKeys, keyEntities, treeData } = this.getStates();
|
|
629
|
-
const { showFilteredOnly, filterTreeNode, treeNodeFilterProp, keyMaps } = this.getProps();
|
|
630
|
+
const { showFilteredOnly, filterTreeNode, treeNodeFilterProp, keyMaps, remote } = this.getProps();
|
|
631
|
+
|
|
632
|
+
// When remote is true, skip local filtering, only update inputValue and trigger onSearch callback
|
|
633
|
+
if (remote) {
|
|
634
|
+
this._adapter.notifySearch(sugInput, [], []);
|
|
635
|
+
this._adapter.rePositionDropdown();
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
|
|
630
639
|
const realFilterProp = treeNodeFilterProp !== 'label' ? treeNodeFilterProp : get(keyMaps, 'label', 'label');
|
|
631
640
|
const newExpandedKeys: Set<string> = new Set(expandedKeys);
|
|
632
641
|
let filteredNodes: BasicTreeNodeData[] = [];
|