@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.
Files changed (180) hide show
  1. package/cascader/foundation.ts +3 -1
  2. package/codeHighlight/codeHighlight.scss +1 -1
  3. package/datePicker/foundation.ts +7 -0
  4. package/datePicker/inputFoundation.ts +5 -0
  5. package/form/foundation.ts +50 -4
  6. package/inputNumber/foundation.ts +119 -3
  7. package/jsonViewer/jsonViewer.scss +2 -2
  8. package/lib/cjs/aiChatInput/aiChatInput.css +7 -7
  9. package/lib/cjs/anchor/anchor.css +3 -3
  10. package/lib/cjs/autoComplete/autoComplete.css +1 -1
  11. package/lib/cjs/avatar/avatar.css +5 -5
  12. package/lib/cjs/badge/badge.css +1 -1
  13. package/lib/cjs/breadcrumb/breadcrumb.css +2 -2
  14. package/lib/cjs/calendar/calendar.css +9 -9
  15. package/lib/cjs/cascader/cascader.css +6 -6
  16. package/lib/cjs/cascader/foundation.js +4 -1
  17. package/lib/cjs/checkbox/checkbox.css +2 -2
  18. package/lib/cjs/codeHighlight/codeHighlight.css +1 -1
  19. package/lib/cjs/codeHighlight/codeHighlight.scss +1 -1
  20. package/lib/cjs/collapse/collapse.css +2 -2
  21. package/lib/cjs/datePicker/datePicker.css +8 -8
  22. package/lib/cjs/datePicker/foundation.d.ts +5 -0
  23. package/lib/cjs/datePicker/foundation.js +2 -0
  24. package/lib/cjs/datePicker/inputFoundation.d.ts +5 -0
  25. package/lib/cjs/descriptions/descriptions.css +6 -6
  26. package/lib/cjs/dropdown/dropdown.css +2 -2
  27. package/lib/cjs/form/form.css +4 -4
  28. package/lib/cjs/form/foundation.js +51 -3
  29. package/lib/cjs/hotKeys/hotKeys.css +2 -2
  30. package/lib/cjs/image/image.css +2 -2
  31. package/lib/cjs/input/input.css +8 -8
  32. package/lib/cjs/input/textarea.css +2 -2
  33. package/lib/cjs/inputNumber/foundation.d.ts +15 -0
  34. package/lib/cjs/inputNumber/foundation.js +113 -3
  35. package/lib/cjs/jsonViewer/jsonViewer.css +2 -2
  36. package/lib/cjs/jsonViewer/jsonViewer.scss +2 -2
  37. package/lib/cjs/list/list.css +1 -1
  38. package/lib/cjs/modal/modal.css +1 -1
  39. package/lib/cjs/navigation/navigation.css +2 -2
  40. package/lib/cjs/notification/notification.css +4 -4
  41. package/lib/cjs/pagination/pagination.css +5 -5
  42. package/lib/cjs/popconfirm/popconfirm.css +1 -1
  43. package/lib/cjs/popover/popover.css +5 -5
  44. package/lib/cjs/radio/radio.css +2 -2
  45. package/lib/cjs/scrollList/itemFoundation.js +12 -0
  46. package/lib/cjs/scrollList/scrollList.css +2 -2
  47. package/lib/cjs/select/select.css +6 -6
  48. package/lib/cjs/sideSheet/sideSheet.css +2 -2
  49. package/lib/cjs/sidebar/sidebar.css +11 -11
  50. package/lib/cjs/slider/foundation.js +46 -12
  51. package/lib/cjs/slider/rtl.scss +62 -0
  52. package/lib/cjs/slider/slider.css +45 -0
  53. package/lib/cjs/slider/slider.scss +2 -0
  54. package/lib/cjs/steps/steps.css +11 -11
  55. package/lib/cjs/table/foundation.d.ts +36 -0
  56. package/lib/cjs/table/foundation.js +162 -28
  57. package/lib/cjs/table/rtl.scss +21 -0
  58. package/lib/cjs/table/table.css +38 -2
  59. package/lib/cjs/table/table.scss +49 -0
  60. package/lib/cjs/tabs/tabs.css +2 -2
  61. package/lib/cjs/tag/tag.css +2 -2
  62. package/lib/cjs/tagInput/tagInput.css +2 -2
  63. package/lib/cjs/timePicker/timePicker.css +1 -1
  64. package/lib/cjs/timeline/timeline.css +2 -2
  65. package/lib/cjs/toast/toast.css +1 -1
  66. package/lib/cjs/tooltip/arrow.scss +4 -4
  67. package/lib/cjs/tooltip/foundation.js +72 -5
  68. package/lib/cjs/tooltip/tooltip.css +5 -5
  69. package/lib/cjs/transfer/constants.d.ts +3 -1
  70. package/lib/cjs/transfer/constants.js +3 -1
  71. package/lib/cjs/transfer/foundation.d.ts +3 -0
  72. package/lib/cjs/transfer/foundation.js +4 -0
  73. package/lib/cjs/transfer/transfer.css +14 -5
  74. package/lib/cjs/transfer/transfer.scss +10 -0
  75. package/lib/cjs/tree/foundation.d.ts +3 -0
  76. package/lib/cjs/tree/foundation.js +31 -4
  77. package/lib/cjs/tree/tree.css +1 -1
  78. package/lib/cjs/treeSelect/foundation.d.ts +1 -0
  79. package/lib/cjs/treeSelect/foundation.js +8 -1
  80. package/lib/cjs/treeSelect/treeSelect.css +36 -4
  81. package/lib/cjs/treeSelect/treeSelect.scss +49 -1
  82. package/lib/cjs/typography/typography.css +8 -8
  83. package/lib/cjs/upload/upload.css +8 -8
  84. package/lib/cjs/utils/Store.d.ts +1 -1
  85. package/lib/cjs/utils/Store.js +1 -0
  86. package/lib/es/aiChatInput/aiChatInput.css +7 -7
  87. package/lib/es/anchor/anchor.css +3 -3
  88. package/lib/es/autoComplete/autoComplete.css +1 -1
  89. package/lib/es/avatar/avatar.css +5 -5
  90. package/lib/es/badge/badge.css +1 -1
  91. package/lib/es/breadcrumb/breadcrumb.css +2 -2
  92. package/lib/es/calendar/calendar.css +9 -9
  93. package/lib/es/cascader/cascader.css +6 -6
  94. package/lib/es/cascader/foundation.js +4 -1
  95. package/lib/es/checkbox/checkbox.css +2 -2
  96. package/lib/es/codeHighlight/codeHighlight.css +1 -1
  97. package/lib/es/codeHighlight/codeHighlight.scss +1 -1
  98. package/lib/es/collapse/collapse.css +2 -2
  99. package/lib/es/datePicker/datePicker.css +8 -8
  100. package/lib/es/datePicker/foundation.d.ts +5 -0
  101. package/lib/es/datePicker/foundation.js +2 -0
  102. package/lib/es/datePicker/inputFoundation.d.ts +5 -0
  103. package/lib/es/descriptions/descriptions.css +6 -6
  104. package/lib/es/dropdown/dropdown.css +2 -2
  105. package/lib/es/form/form.css +4 -4
  106. package/lib/es/form/foundation.js +51 -3
  107. package/lib/es/hotKeys/hotKeys.css +2 -2
  108. package/lib/es/image/image.css +2 -2
  109. package/lib/es/input/input.css +8 -8
  110. package/lib/es/input/textarea.css +2 -2
  111. package/lib/es/inputNumber/foundation.d.ts +15 -0
  112. package/lib/es/inputNumber/foundation.js +113 -3
  113. package/lib/es/jsonViewer/jsonViewer.css +2 -2
  114. package/lib/es/jsonViewer/jsonViewer.scss +2 -2
  115. package/lib/es/list/list.css +1 -1
  116. package/lib/es/modal/modal.css +1 -1
  117. package/lib/es/navigation/navigation.css +2 -2
  118. package/lib/es/notification/notification.css +4 -4
  119. package/lib/es/pagination/pagination.css +5 -5
  120. package/lib/es/popconfirm/popconfirm.css +1 -1
  121. package/lib/es/popover/popover.css +5 -5
  122. package/lib/es/radio/radio.css +2 -2
  123. package/lib/es/scrollList/itemFoundation.js +12 -0
  124. package/lib/es/scrollList/scrollList.css +2 -2
  125. package/lib/es/select/select.css +6 -6
  126. package/lib/es/sideSheet/sideSheet.css +2 -2
  127. package/lib/es/sidebar/sidebar.css +11 -11
  128. package/lib/es/slider/foundation.js +46 -12
  129. package/lib/es/slider/rtl.scss +62 -0
  130. package/lib/es/slider/slider.css +45 -0
  131. package/lib/es/slider/slider.scss +2 -0
  132. package/lib/es/steps/steps.css +11 -11
  133. package/lib/es/table/foundation.d.ts +36 -0
  134. package/lib/es/table/foundation.js +162 -28
  135. package/lib/es/table/rtl.scss +21 -0
  136. package/lib/es/table/table.css +38 -2
  137. package/lib/es/table/table.scss +49 -0
  138. package/lib/es/tabs/tabs.css +2 -2
  139. package/lib/es/tag/tag.css +2 -2
  140. package/lib/es/tagInput/tagInput.css +2 -2
  141. package/lib/es/timePicker/timePicker.css +1 -1
  142. package/lib/es/timeline/timeline.css +2 -2
  143. package/lib/es/toast/toast.css +1 -1
  144. package/lib/es/tooltip/arrow.scss +4 -4
  145. package/lib/es/tooltip/foundation.js +72 -5
  146. package/lib/es/tooltip/tooltip.css +5 -5
  147. package/lib/es/transfer/constants.d.ts +3 -1
  148. package/lib/es/transfer/constants.js +3 -1
  149. package/lib/es/transfer/foundation.d.ts +3 -0
  150. package/lib/es/transfer/foundation.js +4 -0
  151. package/lib/es/transfer/transfer.css +14 -5
  152. package/lib/es/transfer/transfer.scss +10 -0
  153. package/lib/es/tree/foundation.d.ts +3 -0
  154. package/lib/es/tree/foundation.js +31 -4
  155. package/lib/es/tree/tree.css +1 -1
  156. package/lib/es/treeSelect/foundation.d.ts +1 -0
  157. package/lib/es/treeSelect/foundation.js +8 -1
  158. package/lib/es/treeSelect/treeSelect.css +36 -4
  159. package/lib/es/treeSelect/treeSelect.scss +49 -1
  160. package/lib/es/typography/typography.css +8 -8
  161. package/lib/es/upload/upload.css +8 -8
  162. package/lib/es/utils/Store.d.ts +1 -1
  163. package/lib/es/utils/Store.js +1 -0
  164. package/package.json +19 -4
  165. package/scrollList/itemFoundation.ts +12 -0
  166. package/slider/foundation.ts +55 -15
  167. package/slider/rtl.scss +62 -0
  168. package/slider/slider.scss +2 -0
  169. package/table/foundation.ts +197 -29
  170. package/table/rtl.scss +21 -0
  171. package/table/table.scss +49 -0
  172. package/tooltip/arrow.scss +4 -4
  173. package/tooltip/foundation.ts +86 -5
  174. package/transfer/constants.ts +3 -1
  175. package/transfer/foundation.ts +8 -1
  176. package/transfer/transfer.scss +10 -0
  177. package/tree/foundation.ts +34 -5
  178. package/treeSelect/foundation.ts +10 -1
  179. package/treeSelect/treeSelect.scss +49 -1
  180. package/utils/Store.ts +2 -1
@@ -20,6 +20,8 @@ export default class SliderFoundation extends BaseFoundation {
20
20
  min,
21
21
  max
22
22
  } = this._adapter.getProps();
23
+ // Percent always increases with value, independent of visual direction.
24
+ // UI layer decides whether to use `left` or `right` to place elements.
23
25
  const minPercent = range ? (value[0] - min) / (max - min) : (value - min) / (max - min);
24
26
  const maxPercent = range ? (value[1] - min) / (max - min) : 1;
25
27
  return {
@@ -133,6 +135,8 @@ export default class SliderFoundation extends BaseFoundation {
133
135
  verticalReverse,
134
136
  range
135
137
  } = this._adapter.getProps();
138
+ const direction = this._adapter.getContext('direction');
139
+ const isRTL = direction === 'rtl' && !vertical;
136
140
  const value = this._adapter.getState('currentValue');
137
141
  const currentPos = this.transValueToPos(value);
138
142
  const {
@@ -149,6 +153,9 @@ export default class SliderFoundation extends BaseFoundation {
149
153
  let startPos;
150
154
  if (vertical && verticalReverse) {
151
155
  startPos = sliderY + len;
156
+ } else if (isRTL) {
157
+ // In RTL mode, start from right (sliderX + sliderWidth)
158
+ startPos = sliderX + len;
152
159
  } else {
153
160
  startPos = vertical ? sliderY : sliderX;
154
161
  }
@@ -156,11 +163,14 @@ export default class SliderFoundation extends BaseFoundation {
156
163
  let endPos;
157
164
  if (vertical && verticalReverse) {
158
165
  endPos = sliderY;
166
+ } else if (isRTL) {
167
+ // In RTL mode, end at left (sliderX)
168
+ endPos = sliderX;
159
169
  } else {
160
170
  endPos = vertical ? sliderY + sliderHeight : sliderX + sliderWidth;
161
171
  }
162
172
  // endPos = chooseMovePos === 'min' && isDrag && range ? currentPos[1] : endPos;
163
- if (vertical && verticalReverse) {
173
+ if (vertical && verticalReverse || isRTL) {
164
174
  if (position >= startPos) {
165
175
  position = startPos;
166
176
  } else if (position <= endPos) {
@@ -193,6 +203,8 @@ export default class SliderFoundation extends BaseFoundation {
193
203
  step,
194
204
  verticalReverse
195
205
  } = this._adapter.getProps();
206
+ const direction = this._adapter.getContext('direction');
207
+ const isRTL = direction === 'rtl' && !vertical;
196
208
  const {
197
209
  sliderX,
198
210
  sliderY,
@@ -205,6 +217,9 @@ export default class SliderFoundation extends BaseFoundation {
205
217
  if (vertical && verticalReverse) {
206
218
  //isMin = !isMin;
207
219
  stepValue = (startPos + len - pos) / len * (max - min) + min;
220
+ } else if (isRTL) {
221
+ // In RTL mode, position is calculated from right to left
222
+ stepValue = (startPos + len - pos) / len * (max - min) + min;
208
223
  } else {
209
224
  stepValue = (pos - startPos) / len * (max - min) + min;
210
225
  }
@@ -241,6 +256,8 @@ export default class SliderFoundation extends BaseFoundation {
241
256
  range,
242
257
  verticalReverse
243
258
  } = this._adapter.getProps();
259
+ const direction = this._adapter.getContext('direction');
260
+ const isRTL = direction === 'rtl' && !vertical;
244
261
  const {
245
262
  sliderX,
246
263
  sliderY,
@@ -249,10 +266,22 @@ export default class SliderFoundation extends BaseFoundation {
249
266
  } = this._adapter.getSliderLengths();
250
267
  const startPos = vertical ? sliderY : sliderX;
251
268
  const len = vertical ? sliderHeight : sliderWidth;
269
+ const transSingle = val => {
270
+ const percent = (val - min) / (max - min);
271
+ if (vertical && verticalReverse) {
272
+ // Reverse direction in vertical mode
273
+ return startPos + len - percent * len;
274
+ }
275
+ if (isRTL) {
276
+ // Reverse direction in horizontal RTL
277
+ return startPos + len - percent * len;
278
+ }
279
+ return startPos + percent * len;
280
+ };
252
281
  if (range) {
253
- return [(value[0] - min) * len / (max - min) + startPos, (value[1] - min) * len / (max - min) + startPos];
282
+ return [transSingle(value[0]), transSingle(value[1])];
254
283
  } else {
255
- return (value - min) * len / (max - min) + startPos;
284
+ return transSingle(value);
256
285
  }
257
286
  };
258
287
  /**
@@ -575,23 +604,28 @@ export default class SliderFoundation extends BaseFoundation {
575
604
  } = this.getStates();
576
605
  const {
577
606
  step,
578
- range
607
+ range,
608
+ vertical
579
609
  } = this.getProps();
610
+ const direction = this._adapter.getContext('direction');
611
+ const isRTL = direction === 'rtl' && !vertical;
580
612
  let outputValue;
581
613
  switch (event.key) {
582
614
  case "ArrowLeft":
583
615
  case "ArrowDown":
584
- outputValue = this._handleValueDecreaseWithKeyBoard(step, handler);
616
+ // In RTL mode, ArrowLeft and ArrowDown should increase value
617
+ outputValue = isRTL ? this._handleValueIncreaseWithKeyBoard(step, handler) : this._handleValueDecreaseWithKeyBoard(step, handler);
585
618
  break;
586
619
  case "ArrowRight":
587
620
  case "ArrowUp":
588
- outputValue = this._handleValueIncreaseWithKeyBoard(step, handler);
621
+ // In RTL mode, ArrowRight and ArrowUp should decrease value
622
+ outputValue = isRTL ? this._handleValueDecreaseWithKeyBoard(step, handler) : this._handleValueIncreaseWithKeyBoard(step, handler);
589
623
  break;
590
624
  case "PageUp":
591
- outputValue = this._handleValueIncreaseWithKeyBoard(10 * step, handler);
625
+ outputValue = isRTL ? this._handleValueDecreaseWithKeyBoard(10 * step, handler) : this._handleValueIncreaseWithKeyBoard(10 * step, handler);
592
626
  break;
593
627
  case "PageDown":
594
- outputValue = this._handleValueDecreaseWithKeyBoard(10 * step, handler);
628
+ outputValue = isRTL ? this._handleValueIncreaseWithKeyBoard(10 * step, handler) : this._handleValueDecreaseWithKeyBoard(10 * step, handler);
595
629
  break;
596
630
  case "Home":
597
631
  outputValue = this._handleHomeKey(handler);
@@ -712,10 +746,10 @@ export default class SliderFoundation extends BaseFoundation {
712
746
  const currentPos = this.transValueToPos(currentValue);
713
747
  let isMin = true;
714
748
  if (Array.isArray(currentPos)) {
715
- // Slide on both sides
716
- if (pagePos > currentPos[1] || Math.abs(pagePos - currentPos[0]) > Math.abs(pagePos - currentPos[1])) {
717
- isMin = false;
718
- }
749
+ // Choose the nearest handle regardless of ordering (LTR/RTL/verticalReverse)
750
+ const distToFirst = Math.abs(pagePos - currentPos[0]);
751
+ const distToSecond = Math.abs(pagePos - currentPos[1]);
752
+ isMin = distToFirst <= distToSecond;
719
753
  }
720
754
  if (vertical && verticalReverse) {
721
755
  isMin = !isMin;
@@ -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
+ }
@@ -208,4 +208,49 @@
208
208
 
209
209
  .semi-slider-reverse {
210
210
  transform: rotate(180deg);
211
+ }
212
+
213
+ .semi-rtl .semi-slider,
214
+ .semi-portal-rtl .semi-slider {
215
+ direction: rtl;
216
+ }
217
+ .semi-rtl .semi-slider-handle,
218
+ .semi-portal-rtl .semi-slider-handle {
219
+ transform: var(--semi-transform_scale-small) translateX(50%) translateY(0px);
220
+ }
221
+ .semi-rtl .semi-slider-mark,
222
+ .semi-portal-rtl .semi-slider-mark {
223
+ transform: translate(50%, 0);
224
+ }
225
+ .semi-rtl .semi-slider-mark-reverse,
226
+ .semi-portal-rtl .semi-slider-mark-reverse {
227
+ transform: translate(50%, 0) rotate(-180deg);
228
+ }
229
+ .semi-rtl .semi-slider-boundary-min,
230
+ .semi-portal-rtl .semi-slider-boundary-min {
231
+ left: auto;
232
+ right: 0px;
233
+ }
234
+ .semi-rtl .semi-slider-boundary-max,
235
+ .semi-portal-rtl .semi-slider-boundary-max {
236
+ right: auto;
237
+ left: 0px;
238
+ }
239
+
240
+ .semi-slider-rtl .semi-slider-handle {
241
+ transform: var(--semi-transform_scale-small) translateX(50%) translateY(0px);
242
+ }
243
+ .semi-slider-rtl .semi-slider-mark {
244
+ transform: translate(50%, 0);
245
+ }
246
+ .semi-slider-rtl .semi-slider-mark-reverse {
247
+ transform: translate(50%, 0) rotate(-180deg);
248
+ }
249
+ .semi-slider-rtl .semi-slider-boundary-min {
250
+ left: auto;
251
+ right: 0px;
252
+ }
253
+ .semi-slider-rtl .semi-slider-boundary-max {
254
+ right: auto;
255
+ left: 0px;
211
256
  }
@@ -252,3 +252,5 @@ $module: #{$prefix}-slider;
252
252
  .#{$module}-reverse {
253
253
  transform: rotate(180deg);
254
254
  }
255
+
256
+ @import "./rtl.scss";
@@ -25,7 +25,7 @@
25
25
  position: relative;
26
26
  font-size: 18px;
27
27
  line-height: 24px;
28
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
28
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
29
29
  font-weight: 600;
30
30
  width: 100%;
31
31
  overflow: hidden;
@@ -37,7 +37,7 @@
37
37
  .semi-steps .semi-steps-item .semi-steps-item-description {
38
38
  font-size: 14px;
39
39
  line-height: 20px;
40
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
40
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
41
41
  color: var(--semi-color-text-2);
42
42
  width: 100%;
43
43
  overflow: hidden;
@@ -128,7 +128,7 @@
128
128
  justify-content: center;
129
129
  font-size: 20px;
130
130
  line-height: 28px;
131
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
131
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
132
132
  font-weight: 600;
133
133
  flex-grow: 0;
134
134
  }
@@ -183,7 +183,7 @@
183
183
  .semi-steps-basic.semi-steps-horizontal .semi-steps-item .semi-steps-item-description {
184
184
  font-size: 12px;
185
185
  line-height: 16px;
186
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
186
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
187
187
  color: var(--semi-color-text-2);
188
188
  width: 100%;
189
189
  max-width: 268px;
@@ -250,7 +250,7 @@
250
250
  .semi-steps-basic.semi-steps-vertical .semi-steps-item .semi-steps-item-description {
251
251
  font-size: 12px;
252
252
  line-height: 16px;
253
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
253
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
254
254
  color: var(--semi-color-text-2);
255
255
  width: 100%;
256
256
  }
@@ -304,7 +304,7 @@
304
304
  height: 24px;
305
305
  font-size: 16px;
306
306
  line-height: 22px;
307
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
307
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
308
308
  font-weight: 600;
309
309
  background: var(--semi-color-primary);
310
310
  border-radius: var(--semi-border-radius-circle);
@@ -316,7 +316,7 @@
316
316
  display: inline-block;
317
317
  font-size: 16px;
318
318
  line-height: 22px;
319
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
319
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
320
320
  line-height: 24px;
321
321
  font-weight: 600;
322
322
  color: var(--semi-color-text-0);
@@ -366,7 +366,7 @@
366
366
  .semi-steps-basic.semi-steps-small .semi-steps-item .semi-steps-item-title {
367
367
  font-size: 14px;
368
368
  line-height: 20px;
369
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
369
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
370
370
  }
371
371
  .semi-steps-basic.semi-steps-small .semi-steps-item .semi-steps-item-left .semi-steps-item-icon {
372
372
  height: 20px;
@@ -374,7 +374,7 @@
374
374
  .semi-steps-basic.semi-steps-small .semi-steps-item .semi-steps-item-left .semi-steps-item-icon .semi-steps-item-number-icon {
375
375
  font-size: 12px;
376
376
  line-height: 16px;
377
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
377
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
378
378
  width: 20px;
379
379
  height: 20px;
380
380
  }
@@ -411,7 +411,7 @@
411
411
  .semi-steps-nav .semi-steps-item .semi-steps-item-title {
412
412
  font-size: 16px;
413
413
  line-height: 22px;
414
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
414
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
415
415
  max-width: 17em;
416
416
  overflow: hidden;
417
417
  text-overflow: ellipsis;
@@ -425,7 +425,7 @@
425
425
  .semi-steps-nav.semi-steps-small .semi-steps-item .semi-steps-item-title {
426
426
  font-size: 14px;
427
427
  line-height: 20px;
428
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
428
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
429
429
  }
430
430
 
431
431
  .semi-rtl .semi-steps,
@@ -55,8 +55,11 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
55
55
  setFlattenData: (flattenData: RecordType[]) => void;
56
56
  setAllRowKeys: (allRowKeys: BaseRowKeyType[]) => void;
57
57
  setHoveredRowKey: (hoveredRowKey: BaseRowKeyType) => void;
58
+ setHoveredRowKeys: (hoveredRowKeys: BaseRowKeyType[]) => void;
58
59
  setCachedFilteredSortedDataSource: (filteredSortedDataSource: RecordType[]) => void;
59
60
  setCachedFilteredSortedRowKeys: (filteredSortedRowKeys: BaseRowKeyType[]) => void;
61
+ setHalfCheckedRowKeys: (halfCheckedRowKeys: BaseRowKeyType[]) => void;
62
+ setKeyEntities: (keyEntities: BaseEntitys) => void;
60
63
  getCurrentPage: () => number;
61
64
  getCurrentPageSize: () => number;
62
65
  getCachedFilteredSortedDataSource: () => RecordType[];
@@ -65,6 +68,9 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
65
68
  setAllDisabledRowKeys: (allDisabledRowKeys: BaseRowKeyType[]) => void;
66
69
  getAllDisabledRowKeys: () => BaseRowKeyType[];
67
70
  getAllDisabledRowKeysSet: () => Set<BaseRowKeyType>;
71
+ getHalfCheckedRowKeys: () => BaseRowKeyType[];
72
+ getHalfCheckedRowKeysSet: () => Set<BaseRowKeyType>;
73
+ getKeyEntities: () => BaseEntitys;
68
74
  notifyFilterDropdownVisibleChange: (visible: boolean, dataIndex: string) => void;
69
75
  notifyChange: (changeInfo: {
70
76
  pagination: BasePagination;
@@ -90,6 +96,7 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
90
96
  getMergePagination: () => (pagination: BasePagination) => BasePagination;
91
97
  setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void;
92
98
  getTableLayout: () => 'fixed' | 'auto';
99
+ getCheckRelation: () => CheckRelation;
93
100
  }
94
101
  declare class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
95
102
  memoizedWithFnsColumns: (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[], rowSelectionUpdate: boolean, hideExpandedColumn: boolean, bodyHasScrollBar: boolean) => BaseColumnProps<RecordType>[];
@@ -223,6 +230,23 @@ declare class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<Re
223
230
  */
224
231
  getRecordKey(record: RecordType): string;
225
232
  isEmpty(dataSource: RecordType[]): boolean;
233
+ /**
234
+ * Build tree data entities for checkRelation
235
+ * @param dataSource
236
+ * @returns keyEntities map
237
+ */
238
+ buildKeyEntities(dataSource?: RecordType[]): BaseEntitys;
239
+ /**
240
+ * Calculate checked keys when checkRelation is 'related'
241
+ * @param realKey
242
+ * @param selected
243
+ * @param checkedKeys
244
+ * @param halfCheckedKeys
245
+ */
246
+ calcCheckedKeysForSelect(realKey: BaseRowKeyType, selected: boolean, checkedKeys: Set<string>, halfCheckedKeys: Set<string>): {
247
+ checkedKeys: Set<string>;
248
+ halfCheckedKeys: Set<string>;
249
+ };
226
250
  handleSelectRow(realKey: BaseRowKeyType, selected: boolean, e: any): void;
227
251
  /**
228
252
  * select all rows
@@ -381,4 +405,16 @@ export type BaseIncludeGroupRecord<RecordType> = RecordType | {
381
405
  export type BaseEllipsis = boolean | {
382
406
  showTitle: boolean;
383
407
  };
408
+ export type CheckRelation = 'related' | 'unRelated';
409
+ export interface BaseEntity {
410
+ key?: string | number;
411
+ level?: number;
412
+ children?: BaseEntity[];
413
+ parent?: BaseEntity | null;
414
+ data?: Record<string, any>;
415
+ [key: string]: any;
416
+ }
417
+ export interface BaseEntitys {
418
+ [key: string]: BaseEntity;
419
+ }
384
420
  export default TableFoundation;
@@ -16,6 +16,7 @@ import BaseFoundation from '../base/foundation';
16
16
  import { strings, numbers } from './constants';
17
17
  import { mergeQueries, flattenColumns, filterColumns } from './utils';
18
18
  import { pullAll, withOrderSort } from '../utils/array';
19
+ import { convertDataToEntities, calcCheckedKeysForChecked, calcCheckedKeysForUnchecked } from '../tree/treeUtil';
19
20
  class TableFoundation extends BaseFoundation {
20
21
  /**
21
22
  * update columns in place, and use default values as initial values if the sorting and filtering columns have no values
@@ -587,29 +588,115 @@ class TableFoundation extends BaseFoundation {
587
588
  dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
588
589
  return !(Array.isArray(dataSource) && dataSource.length > 0);
589
590
  }
591
+ /**
592
+ * Build tree data entities for checkRelation
593
+ * @param dataSource
594
+ * @returns keyEntities map
595
+ */
596
+ buildKeyEntities(dataSource) {
597
+ dataSource = dataSource == null ? this._getDataSource() : dataSource;
598
+ const childrenRecordName = this.getProp('childrenRecordName');
599
+ const rowKey = this.getProp('rowKey');
600
+ // Convert table data to tree data format
601
+ const convertToTreeData = data => {
602
+ return data.map(record => {
603
+ const key = typeof rowKey === 'function' ? rowKey(record) : _get(record, rowKey);
604
+ const children = _get(record, childrenRecordName);
605
+ const node = Object.assign({
606
+ key
607
+ }, record);
608
+ if (Array.isArray(children) && children.length) {
609
+ node.children = convertToTreeData(children);
610
+ }
611
+ return node;
612
+ });
613
+ };
614
+ const treeData = convertToTreeData(dataSource);
615
+ const {
616
+ keyEntities
617
+ } = convertDataToEntities(treeData, {
618
+ key: 'key',
619
+ children: 'children'
620
+ });
621
+ return keyEntities;
622
+ }
623
+ /**
624
+ * Calculate checked keys when checkRelation is 'related'
625
+ * @param realKey
626
+ * @param selected
627
+ * @param checkedKeys
628
+ * @param halfCheckedKeys
629
+ */
630
+ calcCheckedKeysForSelect(realKey, selected, checkedKeys, halfCheckedKeys) {
631
+ const keyEntities = this._adapter.getKeyEntities();
632
+ const keyStr = String(realKey);
633
+ // If keyEntities doesn't contain this key, handle it as a simple add/remove
634
+ if (!keyEntities || !keyEntities[keyStr]) {
635
+ if (selected) {
636
+ checkedKeys.add(keyStr);
637
+ } else {
638
+ checkedKeys.delete(keyStr);
639
+ }
640
+ return {
641
+ checkedKeys,
642
+ halfCheckedKeys
643
+ };
644
+ }
645
+ if (selected) {
646
+ return calcCheckedKeysForChecked(keyStr, keyEntities, checkedKeys, halfCheckedKeys);
647
+ } else {
648
+ return calcCheckedKeysForUnchecked(keyStr, keyEntities, checkedKeys, halfCheckedKeys);
649
+ }
650
+ }
590
651
  handleSelectRow(realKey, selected, e) {
591
652
  this.stopPropagation(e);
592
653
  if (typeof selected === 'boolean' && realKey != null) {
654
+ const checkRelation = this._adapter.getCheckRelation();
593
655
  const selectedRowKeys = this._getSelectedRowKeys();
656
+ const halfCheckedRowKeys = [...(this._adapter.getHalfCheckedRowKeys() || [])];
594
657
  let foundIdx = -1;
595
658
  const selectedRow = this.getSelectedRows(null, [realKey])[0];
596
659
  let selectedRows;
597
- if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
598
- selectedRowKeys.splice(foundIdx, 1);
599
- selectedRows = this.getSelectedRows(null, selectedRowKeys);
660
+ if (checkRelation === 'related') {
661
+ // When checkRelation is 'related', use tree selection logic
662
+ const keyEntities = this._adapter.getKeyEntities();
663
+ // Convert keys to strings for tree utility functions
664
+ const checkedKeysSet = new Set(selectedRowKeys.map(key => String(key)));
665
+ const halfCheckedKeysSet = new Set(halfCheckedRowKeys.map(key => String(key)));
666
+ const {
667
+ checkedKeys,
668
+ halfCheckedKeys
669
+ } = this.calcCheckedKeysForSelect(String(realKey), selected, checkedKeysSet, halfCheckedKeysSet);
670
+ const newSelectedRowKeys = [...checkedKeys];
671
+ const newHalfCheckedRowKeys = [...halfCheckedKeys];
672
+ selectedRows = this.getSelectedRows(null, newSelectedRowKeys);
673
+ // Always update halfCheckedRowKeys state for checkRelation='related' mode
674
+ // This is needed for rendering the half-checked state in the UI
675
+ this._adapter.setHalfCheckedRowKeys(newHalfCheckedRowKeys);
600
676
  if (!this._selectionIsControlled()) {
601
- this._adapter.setSelectedRowKeys(selectedRowKeys);
677
+ this._adapter.setSelectedRowKeys(newSelectedRowKeys);
602
678
  }
603
679
  this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
604
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
605
- } else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
606
- selectedRowKeys.push(realKey);
607
- selectedRows = this.getSelectedRows(null, selectedRowKeys);
608
- if (!this._selectionIsControlled()) {
609
- this._adapter.setSelectedRowKeys(selectedRowKeys);
680
+ this._adapter.notifySelectionChange(newSelectedRowKeys, selectedRows);
681
+ } else {
682
+ // Original logic for unRelated mode
683
+ if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
684
+ selectedRowKeys.splice(foundIdx, 1);
685
+ selectedRows = this.getSelectedRows(null, selectedRowKeys);
686
+ if (!this._selectionIsControlled()) {
687
+ this._adapter.setSelectedRowKeys(selectedRowKeys);
688
+ }
689
+ this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
690
+ this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
691
+ } else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
692
+ selectedRowKeys.push(realKey);
693
+ selectedRows = this.getSelectedRows(null, selectedRowKeys);
694
+ if (!this._selectionIsControlled()) {
695
+ this._adapter.setSelectedRowKeys(selectedRowKeys);
696
+ }
697
+ this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
698
+ this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
610
699
  }
611
- this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
612
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
613
700
  }
614
701
  }
615
702
  }
@@ -621,6 +708,7 @@ class TableFoundation extends BaseFoundation {
621
708
  handleSelectAllRow(selected, e) {
622
709
  this.stopPropagation(e);
623
710
  if (typeof selected === 'boolean') {
711
+ const checkRelation = this._adapter.getCheckRelation();
624
712
  const curSelectedRowKeys = this._getSelectedRowKeys();
625
713
  let selectedRowKeys = [...curSelectedRowKeys];
626
714
  const selectedRowKeysSet = this._getSelectedRowKeysSet();
@@ -628,26 +716,72 @@ class TableFoundation extends BaseFoundation {
628
716
  const disabledRowKeys = this._adapter.getAllDisabledRowKeys();
629
717
  const disabledRowKeysSet = this._adapter.getAllDisabledRowKeysSet();
630
718
  let changedRowKeys;
631
- // Select all, if not disabled && not in selectedRowKeys
632
- if (selected) {
633
- for (const key of allRowKeys) {
634
- if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
635
- selectedRowKeys.push(key);
719
+ if (checkRelation === 'related') {
720
+ // When checkRelation is 'related', use tree selection logic
721
+ const keyEntities = this._adapter.getKeyEntities();
722
+ const halfCheckedRowKeys = [...(this._adapter.getHalfCheckedRowKeys() || [])];
723
+ // Convert keys to strings for tree utility functions
724
+ let checkedKeysSet = new Set(selectedRowKeys.map(key => String(key)));
725
+ let halfCheckedKeysSet = new Set(halfCheckedRowKeys.map(key => String(key)));
726
+ if (selected) {
727
+ // Select all: add all non-disabled keys
728
+ const keysToAdd = allRowKeys.filter(key => !disabledRowKeysSet.has(key));
729
+ for (const key of keysToAdd) {
730
+ const keyStr = String(key);
731
+ if (!checkedKeysSet.has(keyStr) && keyEntities && keyEntities[keyStr]) {
732
+ const result = calcCheckedKeysForChecked(keyStr, keyEntities, checkedKeysSet, halfCheckedKeysSet);
733
+ checkedKeysSet = result.checkedKeys;
734
+ halfCheckedKeysSet = result.halfCheckedKeys;
735
+ }
736
+ }
737
+ changedRowKeys = keysToAdd;
738
+ } else {
739
+ // Deselect all: remove all keys
740
+ const keysToRemove = [...checkedKeysSet];
741
+ for (const key of keysToRemove) {
742
+ if (keyEntities && keyEntities[key]) {
743
+ const result = calcCheckedKeysForUnchecked(key, keyEntities, checkedKeysSet, halfCheckedKeysSet);
744
+ checkedKeysSet = result.checkedKeys;
745
+ halfCheckedKeysSet = result.halfCheckedKeys;
746
+ }
636
747
  }
748
+ changedRowKeys = [...curSelectedRowKeys];
637
749
  }
638
- allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
639
- changedRowKeys = [...allRowKeys];
750
+ selectedRowKeys = [...checkedKeysSet];
751
+ const newHalfCheckedRowKeys = [...halfCheckedKeysSet];
752
+ const changedRows = this.getSelectedRows(null, changedRowKeys || []);
753
+ const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
754
+ // Always update halfCheckedRowKeys state for checkRelation='related' mode
755
+ // This is needed for rendering the half-checked state in the UI
756
+ this._adapter.setHalfCheckedRowKeys(newHalfCheckedRowKeys);
757
+ if (!this._selectionIsControlled()) {
758
+ this._adapter.setSelectedRowKeys(selectedRowKeys);
759
+ }
760
+ this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
761
+ this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
640
762
  } else {
641
- selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
642
- changedRowKeys = [...curSelectedRowKeys];
643
- }
644
- const changedRows = this.getSelectedRows(null, changedRowKeys || []);
645
- const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
646
- if (!this._selectionIsControlled()) {
647
- this._adapter.setSelectedRowKeys(selectedRowKeys);
763
+ // Original logic for unRelated mode
764
+ // Select all, if not disabled && not in selectedRowKeys
765
+ if (selected) {
766
+ for (const key of allRowKeys) {
767
+ if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
768
+ selectedRowKeys.push(key);
769
+ }
770
+ }
771
+ allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
772
+ changedRowKeys = [...allRowKeys];
773
+ } else {
774
+ selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
775
+ changedRowKeys = [...curSelectedRowKeys];
776
+ }
777
+ const changedRows = this.getSelectedRows(null, changedRowKeys || []);
778
+ const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
779
+ if (!this._selectionIsControlled()) {
780
+ this._adapter.setSelectedRowKeys(selectedRowKeys);
781
+ }
782
+ this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
783
+ this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
648
784
  }
649
- this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
650
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
651
785
  }
652
786
  }
653
787
  /**