@douyinfe/semi-foundation 2.97.0 → 2.99.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/cascader/foundation.ts +3 -1
- package/codeHighlight/codeHighlight.scss +1 -1
- package/datePicker/foundation.ts +7 -0
- package/datePicker/inputFoundation.ts +5 -0
- package/form/foundation.ts +50 -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/cascader/foundation.js +4 -1
- 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 +51 -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 +5 -5
- 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/rtl.scss +21 -0
- package/lib/cjs/table/table.css +38 -2
- package/lib/cjs/table/table.scss +49 -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/arrow.scss +4 -4
- package/lib/cjs/tooltip/foundation.js +72 -5
- package/lib/cjs/tooltip/tooltip.css +5 -5
- 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/cascader/foundation.js +4 -1
- 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 +51 -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 +5 -5
- 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/rtl.scss +21 -0
- package/lib/es/table/table.css +38 -2
- package/lib/es/table/table.scss +49 -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/arrow.scss +4 -4
- package/lib/es/tooltip/foundation.js +72 -5
- package/lib/es/tooltip/tooltip.css +5 -5
- 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/rtl.scss +21 -0
- package/table/table.scss +49 -0
- package/tooltip/arrow.scss +4 -4
- package/tooltip/foundation.ts +86 -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/rtl.scss
CHANGED
|
@@ -144,6 +144,27 @@ $module: #{$prefix}-table;
|
|
|
144
144
|
border-left: $width-table_base_border $border-table_base-borderStyle $color-table-border-default;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
// Fix #441 (RTL): when horizontal scroll is enabled and table is NOT scrolled to the far left,
|
|
149
|
+
// the outer left border can be outside of viewport (the real border is rendered by the last column cell).
|
|
150
|
+
// Draw an overlay left border on the container to keep it visible.
|
|
151
|
+
// When scrolled to the far left, `.semi-table-scroll-position-left` exists and we should not draw it.
|
|
152
|
+
&:not(.#{$module}-scroll-position-left) {
|
|
153
|
+
& > .#{$module}-container {
|
|
154
|
+
&::after {
|
|
155
|
+
content: '';
|
|
156
|
+
position: absolute;
|
|
157
|
+
top: 0;
|
|
158
|
+
left: 0;
|
|
159
|
+
bottom: 0;
|
|
160
|
+
width: $width-table_base_border;
|
|
161
|
+
background-color: $color-table-border-default;
|
|
162
|
+
display: block;
|
|
163
|
+
z-index: $z-table_fixed_column + 2;
|
|
164
|
+
pointer-events: none;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
147
168
|
}
|
|
148
169
|
|
|
149
170
|
&-fixed {
|
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\
|
|
@@ -538,6 +555,35 @@ $module: #{$prefix}-table;
|
|
|
538
555
|
}
|
|
539
556
|
}
|
|
540
557
|
|
|
558
|
+
// Fix #441: when horizontal scroll is enabled (e.g. scroll.x='101%') and table is NOT scrolled to the far right,
|
|
559
|
+
// the outer right border can be outside of viewport because the real right border is rendered by the
|
|
560
|
+
// last column cell border (which is scrollable). Draw an overlay right border on the container to keep it visible.
|
|
561
|
+
// When scrolled to the far right, `.semi-table-scroll-position-right` exists and we should not draw it to avoid
|
|
562
|
+
// double borders.
|
|
563
|
+
&:not(.#{$module}-scroll-position-right) {
|
|
564
|
+
& > .#{$module}-container {
|
|
565
|
+
&::after {
|
|
566
|
+
content: '';
|
|
567
|
+
position: absolute;
|
|
568
|
+
top: 0;
|
|
569
|
+
right: 0;
|
|
570
|
+
bottom: 0;
|
|
571
|
+
width: $width-table_base_border;
|
|
572
|
+
background-color: $color-table-border-default;
|
|
573
|
+
display: block;
|
|
574
|
+
// Make sure the overlay border stays above table content/fixed columns
|
|
575
|
+
z-index: $z-table_fixed_column + 2;
|
|
576
|
+
pointer-events: none;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Ensure header shows a visible right border even when the container overlay
|
|
580
|
+
// is covered by native scrollbars in some browsers.
|
|
581
|
+
& > .#{$module}-header {
|
|
582
|
+
box-shadow: inset -$width-table_base_border 0 0 0 $color-table-border-default;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
541
587
|
:where(& > .#{$module}-container) {
|
|
542
588
|
& > .#{$module}-body > .#{$module}-placeholder {
|
|
543
589
|
border-right: $width-table_base_border $border-table_base-borderStyle $color-table-border-default;
|
|
@@ -572,6 +618,9 @@ $module: #{$prefix}-table;
|
|
|
572
618
|
position: sticky;
|
|
573
619
|
left: 0px;
|
|
574
620
|
z-index: 1;
|
|
621
|
+
// In bordered mode, placeholder may receive an extra side border to complete the outer frame.
|
|
622
|
+
// Use border-box to avoid 1px horizontal overflow (and unwanted horizontal scrollbar) in empty data + scroll.y cases.
|
|
623
|
+
box-sizing: border-box;
|
|
575
624
|
padding: #{$spacing-table-paddingY} #{$spacing-table-paddingX};
|
|
576
625
|
color: $color-table_placeholder-text-default;
|
|
577
626
|
font-size: #{$font-table_base-fontSize};
|
package/tooltip/arrow.scss
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
&[x-placement='top'] {
|
|
25
25
|
.#{$module-icon} {
|
|
26
|
-
left: 50
|
|
26
|
+
left: var(--semi-tooltip-arrow-offset-x, 50%);
|
|
27
27
|
transform: translateX(-50%);
|
|
28
28
|
bottom: (-$height-tooltip_arrow + $spacing-tooltip_arrow_offset-y);
|
|
29
29
|
}
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
width: $width-tooltip_arrow_vertical;
|
|
62
62
|
height: $height-tooltip_arrow_vertical;
|
|
63
63
|
right: (-$width-tooltip_arrow_vertical + $spacing-tooltip_arrow_offset-x);
|
|
64
|
-
top: 50
|
|
64
|
+
top: var(--semi-tooltip-arrow-offset-y, 50%);
|
|
65
65
|
transform: translateY(-50%);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
width: $width-tooltip_arrow_vertical;
|
|
94
94
|
height: $height-tooltip_arrow_vertical;
|
|
95
95
|
left: -$width-tooltip_arrow_vertical + $spacing-tooltip_arrow_offset-x;
|
|
96
|
-
top: 50
|
|
96
|
+
top: var(--semi-tooltip-arrow-offset-y, 50%);
|
|
97
97
|
transform: translateY(-50%) rotate(180deg);
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
&[x-placement='bottom'] {
|
|
123
123
|
.#{$module-icon} {
|
|
124
124
|
top: (-$height-tooltip_arrow + $spacing-tooltip_arrow_offset-y);
|
|
125
|
-
left: 50
|
|
125
|
+
left: var(--semi-tooltip-arrow-offset-x, 50%);
|
|
126
126
|
transform: translateX(-50%) rotate(180deg);
|
|
127
127
|
}
|
|
128
128
|
|
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
|
};
|
|
@@ -671,12 +674,90 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
|
|
|
671
674
|
}
|
|
672
675
|
}
|
|
673
676
|
|
|
677
|
+
// Handle arrowPointAtCenter for center positions (top/bottom/left/right)
|
|
678
|
+
// For center positions, the arrow needs to point at trigger center, not Popover center
|
|
679
|
+
let cssArrowOffsetX: string | undefined;
|
|
680
|
+
let cssArrowOffsetY: string | undefined;
|
|
681
|
+
|
|
682
|
+
if (showArrow) {
|
|
683
|
+
const isCenterPosition = ['top', 'bottom', 'left', 'right'].includes(position);
|
|
684
|
+
|
|
685
|
+
if (isCenterPosition) {
|
|
686
|
+
if (arrowPointAtCenter) {
|
|
687
|
+
// arrowPointAtCenter=true: arrow should point at trigger center
|
|
688
|
+
// Calculate arrow position relative to Popover left/top edge
|
|
689
|
+
|
|
690
|
+
if ((position === 'top' || position === 'bottom') && wrapperRect.width > 0) {
|
|
691
|
+
// Popover center is at `left`, trigger center is at `middleX`
|
|
692
|
+
// Arrow position from Popover left edge:
|
|
693
|
+
// = middleX - (left - wrapperRect.width/2)
|
|
694
|
+
// = middleX - left + wrapperRect.width/2
|
|
695
|
+
// Percentage: (middleX - left) / wrapperRect.width + 0.5
|
|
696
|
+
const arrowOffsetPercent = (middleX - left) / wrapperRect.width + 0.5;
|
|
697
|
+
|
|
698
|
+
// Clamp to valid range to prevent arrow going outside Popover
|
|
699
|
+
const minOffset = (horizontalArrowWidth / 2 + positionOffsetX) / wrapperRect.width;
|
|
700
|
+
const maxOffset = 1 - minOffset;
|
|
701
|
+
const clampedOffset = Math.max(minOffset, Math.min(maxOffset, arrowOffsetPercent));
|
|
702
|
+
|
|
703
|
+
// Only set CSS variable if different from default 50%
|
|
704
|
+
if (Math.abs(clampedOffset - 0.5) > 0.01) {
|
|
705
|
+
cssArrowOffsetX = `${clampedOffset * 100}%`;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
if ((position === 'left' || position === 'right') && wrapperRect.height > 0) {
|
|
710
|
+
const arrowOffsetPercent = (middleY - top) / wrapperRect.height + 0.5;
|
|
711
|
+
|
|
712
|
+
const minOffset = (verticalArrowHeight / 2 + positionOffsetY) / wrapperRect.height;
|
|
713
|
+
const maxOffset = 1 - minOffset;
|
|
714
|
+
const clampedOffset = Math.max(minOffset, Math.min(maxOffset, arrowOffsetPercent));
|
|
715
|
+
|
|
716
|
+
if (Math.abs(clampedOffset - 0.5) > 0.01) {
|
|
717
|
+
cssArrowOffsetY = `${clampedOffset * 100}%`;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
} else {
|
|
721
|
+
// arrowPointAtCenter=false: arrow should be at Popover edge
|
|
722
|
+
// Determine which edge based on trigger position in viewport
|
|
723
|
+
|
|
724
|
+
if ((position === 'top' || position === 'bottom') && wrapperRect.width > 0) {
|
|
725
|
+
const offsetXWithArrow = positionOffsetX + horizontalArrowWidth / 2;
|
|
726
|
+
|
|
727
|
+
if (isTriggerNearLeft) {
|
|
728
|
+
cssArrowOffsetX = `${(offsetXWithArrow / wrapperRect.width) * 100}%`;
|
|
729
|
+
} else {
|
|
730
|
+
cssArrowOffsetX = `${((wrapperRect.width - offsetXWithArrow) / wrapperRect.width) * 100}%`;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if ((position === 'left' || position === 'right') && wrapperRect.height > 0) {
|
|
735
|
+
const offsetYWithArrow = positionOffsetY + verticalArrowHeight / 2;
|
|
736
|
+
|
|
737
|
+
if (isTriggerNearTop) {
|
|
738
|
+
cssArrowOffsetY = `${(offsetYWithArrow / wrapperRect.height) * 100}%`;
|
|
739
|
+
} else {
|
|
740
|
+
cssArrowOffsetY = `${((wrapperRect.height - offsetYWithArrow) / wrapperRect.height) * 100}%`;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
674
747
|
// The left/top value here must be rounded, otherwise it will cause the small triangle to shake
|
|
675
748
|
const style: Record<string, string | number> = {
|
|
676
749
|
left: this._roundPixel(left),
|
|
677
750
|
top: this._roundPixel(top),
|
|
678
751
|
};
|
|
679
752
|
|
|
753
|
+
// Add CSS variables for arrow positioning
|
|
754
|
+
if (cssArrowOffsetX) {
|
|
755
|
+
style['--semi-tooltip-arrow-offset-x'] = cssArrowOffsetX;
|
|
756
|
+
}
|
|
757
|
+
if (cssArrowOffsetY) {
|
|
758
|
+
style['--semi-tooltip-arrow-offset-y'] = cssArrowOffsetY;
|
|
759
|
+
}
|
|
760
|
+
|
|
680
761
|
let transform = '';
|
|
681
762
|
|
|
682
763
|
if (translateX != null) {
|