@douyinfe/semi-foundation 2.96.1 → 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.
Files changed (235) hide show
  1. package/cascader/foundation.ts +74 -19
  2. package/codeHighlight/codeHighlight.scss +1 -1
  3. package/datePicker/datePicker.scss +100 -5
  4. package/datePicker/foundation.ts +7 -0
  5. package/datePicker/inputFoundation.ts +5 -0
  6. package/form/foundation.ts +55 -7
  7. package/form/utils.ts +7 -2
  8. package/image/previewImageFoundation.ts +34 -3
  9. package/image/previewInnerFoundation.ts +15 -4
  10. package/input/textarea.scss +35 -0
  11. package/inputNumber/foundation.ts +119 -3
  12. package/jsonViewer/jsonViewer.scss +2 -2
  13. package/lib/cjs/aiChatInput/aiChatInput.css +7 -7
  14. package/lib/cjs/anchor/anchor.css +3 -3
  15. package/lib/cjs/autoComplete/autoComplete.css +1 -1
  16. package/lib/cjs/avatar/avatar.css +5 -5
  17. package/lib/cjs/badge/badge.css +1 -1
  18. package/lib/cjs/breadcrumb/breadcrumb.css +2 -2
  19. package/lib/cjs/calendar/calendar.css +9 -9
  20. package/lib/cjs/cascader/cascader.css +6 -6
  21. package/lib/cjs/cascader/foundation.d.ts +12 -0
  22. package/lib/cjs/cascader/foundation.js +68 -23
  23. package/lib/cjs/checkbox/checkbox.css +2 -2
  24. package/lib/cjs/codeHighlight/codeHighlight.css +1 -1
  25. package/lib/cjs/codeHighlight/codeHighlight.scss +1 -1
  26. package/lib/cjs/collapse/collapse.css +2 -2
  27. package/lib/cjs/datePicker/datePicker.css +75 -13
  28. package/lib/cjs/datePicker/datePicker.scss +100 -5
  29. package/lib/cjs/datePicker/foundation.d.ts +5 -0
  30. package/lib/cjs/datePicker/foundation.js +2 -0
  31. package/lib/cjs/datePicker/inputFoundation.d.ts +5 -0
  32. package/lib/cjs/descriptions/descriptions.css +6 -6
  33. package/lib/cjs/dropdown/dropdown.css +2 -2
  34. package/lib/cjs/form/form.css +4 -4
  35. package/lib/cjs/form/foundation.d.ts +1 -1
  36. package/lib/cjs/form/foundation.js +55 -9
  37. package/lib/cjs/form/utils.js +5 -2
  38. package/lib/cjs/hotKeys/hotKeys.css +2 -2
  39. package/lib/cjs/image/image.css +2 -2
  40. package/lib/cjs/image/previewImageFoundation.d.ts +4 -0
  41. package/lib/cjs/image/previewImageFoundation.js +33 -2
  42. package/lib/cjs/image/previewInnerFoundation.d.ts +1 -0
  43. package/lib/cjs/image/previewInnerFoundation.js +17 -4
  44. package/lib/cjs/input/input.css +8 -8
  45. package/lib/cjs/input/textarea.css +19 -2
  46. package/lib/cjs/input/textarea.scss +35 -0
  47. package/lib/cjs/inputNumber/foundation.d.ts +15 -0
  48. package/lib/cjs/inputNumber/foundation.js +113 -3
  49. package/lib/cjs/jsonViewer/jsonViewer.css +2 -2
  50. package/lib/cjs/jsonViewer/jsonViewer.scss +2 -2
  51. package/lib/cjs/list/list.css +1 -1
  52. package/lib/cjs/modal/modal.css +1 -1
  53. package/lib/cjs/navigation/navigation.css +4 -3
  54. package/lib/cjs/navigation/navigation.scss +1 -0
  55. package/lib/cjs/navigation/variables.scss +1 -1
  56. package/lib/cjs/notification/notification.css +4 -4
  57. package/lib/cjs/overflowList/foundation.d.ts +1 -0
  58. package/lib/cjs/overflowList/foundation.js +51 -1
  59. package/lib/cjs/pagination/pagination.css +5 -5
  60. package/lib/cjs/popconfirm/popconfirm.css +1 -1
  61. package/lib/cjs/popover/popover.css +1 -1
  62. package/lib/cjs/radio/radio.css +2 -2
  63. package/lib/cjs/scrollList/itemFoundation.js +12 -0
  64. package/lib/cjs/scrollList/scrollList.css +2 -2
  65. package/lib/cjs/select/foundation.d.ts +1 -1
  66. package/lib/cjs/select/foundation.js +28 -2
  67. package/lib/cjs/select/select.css +6 -6
  68. package/lib/cjs/sideSheet/sideSheet.css +2 -2
  69. package/lib/cjs/sidebar/sidebar.css +11 -11
  70. package/lib/cjs/slider/foundation.js +46 -12
  71. package/lib/cjs/slider/rtl.scss +62 -0
  72. package/lib/cjs/slider/slider.css +45 -0
  73. package/lib/cjs/slider/slider.scss +2 -0
  74. package/lib/cjs/steps/steps.css +11 -11
  75. package/lib/cjs/switch/switch.css +1 -0
  76. package/lib/cjs/switch/switch.scss +1 -0
  77. package/lib/cjs/switch/variables.scss +2 -1
  78. package/lib/cjs/table/foundation.d.ts +36 -0
  79. package/lib/cjs/table/foundation.js +164 -29
  80. package/lib/cjs/table/table.css +10 -2
  81. package/lib/cjs/table/table.scss +17 -0
  82. package/lib/cjs/tabs/tabs.css +2 -2
  83. package/lib/cjs/tag/tag.css +28 -2
  84. package/lib/cjs/tag/tag.scss +33 -0
  85. package/lib/cjs/tagInput/tagInput.css +19 -2
  86. package/lib/cjs/tagInput/tagInput.scss +18 -0
  87. package/lib/cjs/timePicker/constants.d.ts +1 -0
  88. package/lib/cjs/timePicker/foundation.d.ts +7 -1
  89. package/lib/cjs/timePicker/foundation.js +62 -11
  90. package/lib/cjs/timePicker/timePicker.css +1 -1
  91. package/lib/cjs/timeline/timeline.css +2 -2
  92. package/lib/cjs/toast/toast.css +1 -1
  93. package/lib/cjs/tooltip/foundation.js +8 -5
  94. package/lib/cjs/tooltip/tooltip.css +1 -1
  95. package/lib/cjs/transfer/constants.d.ts +3 -1
  96. package/lib/cjs/transfer/constants.js +3 -1
  97. package/lib/cjs/transfer/foundation.d.ts +3 -0
  98. package/lib/cjs/transfer/foundation.js +4 -0
  99. package/lib/cjs/transfer/transfer.css +14 -5
  100. package/lib/cjs/transfer/transfer.scss +10 -0
  101. package/lib/cjs/tree/foundation.d.ts +3 -0
  102. package/lib/cjs/tree/foundation.js +31 -4
  103. package/lib/cjs/tree/tree.css +1 -1
  104. package/lib/cjs/treeSelect/foundation.d.ts +1 -0
  105. package/lib/cjs/treeSelect/foundation.js +8 -1
  106. package/lib/cjs/treeSelect/treeSelect.css +36 -4
  107. package/lib/cjs/treeSelect/treeSelect.scss +49 -1
  108. package/lib/cjs/typography/typography.css +8 -8
  109. package/lib/cjs/upload/upload.css +8 -8
  110. package/lib/cjs/utils/Store.d.ts +1 -1
  111. package/lib/cjs/utils/Store.js +1 -0
  112. package/lib/es/aiChatInput/aiChatInput.css +7 -7
  113. package/lib/es/anchor/anchor.css +3 -3
  114. package/lib/es/autoComplete/autoComplete.css +1 -1
  115. package/lib/es/avatar/avatar.css +5 -5
  116. package/lib/es/badge/badge.css +1 -1
  117. package/lib/es/breadcrumb/breadcrumb.css +2 -2
  118. package/lib/es/calendar/calendar.css +9 -9
  119. package/lib/es/cascader/cascader.css +6 -6
  120. package/lib/es/cascader/foundation.d.ts +12 -0
  121. package/lib/es/cascader/foundation.js +68 -23
  122. package/lib/es/checkbox/checkbox.css +2 -2
  123. package/lib/es/codeHighlight/codeHighlight.css +1 -1
  124. package/lib/es/codeHighlight/codeHighlight.scss +1 -1
  125. package/lib/es/collapse/collapse.css +2 -2
  126. package/lib/es/datePicker/datePicker.css +75 -13
  127. package/lib/es/datePicker/datePicker.scss +100 -5
  128. package/lib/es/datePicker/foundation.d.ts +5 -0
  129. package/lib/es/datePicker/foundation.js +2 -0
  130. package/lib/es/datePicker/inputFoundation.d.ts +5 -0
  131. package/lib/es/descriptions/descriptions.css +6 -6
  132. package/lib/es/dropdown/dropdown.css +2 -2
  133. package/lib/es/form/form.css +4 -4
  134. package/lib/es/form/foundation.d.ts +1 -1
  135. package/lib/es/form/foundation.js +55 -9
  136. package/lib/es/form/utils.js +5 -2
  137. package/lib/es/hotKeys/hotKeys.css +2 -2
  138. package/lib/es/image/image.css +2 -2
  139. package/lib/es/image/previewImageFoundation.d.ts +4 -0
  140. package/lib/es/image/previewImageFoundation.js +33 -2
  141. package/lib/es/image/previewInnerFoundation.d.ts +1 -0
  142. package/lib/es/image/previewInnerFoundation.js +17 -4
  143. package/lib/es/input/input.css +8 -8
  144. package/lib/es/input/textarea.css +19 -2
  145. package/lib/es/input/textarea.scss +35 -0
  146. package/lib/es/inputNumber/foundation.d.ts +15 -0
  147. package/lib/es/inputNumber/foundation.js +113 -3
  148. package/lib/es/jsonViewer/jsonViewer.css +2 -2
  149. package/lib/es/jsonViewer/jsonViewer.scss +2 -2
  150. package/lib/es/list/list.css +1 -1
  151. package/lib/es/modal/modal.css +1 -1
  152. package/lib/es/navigation/navigation.css +4 -3
  153. package/lib/es/navigation/navigation.scss +1 -0
  154. package/lib/es/navigation/variables.scss +1 -1
  155. package/lib/es/notification/notification.css +4 -4
  156. package/lib/es/overflowList/foundation.d.ts +1 -0
  157. package/lib/es/overflowList/foundation.js +51 -1
  158. package/lib/es/pagination/pagination.css +5 -5
  159. package/lib/es/popconfirm/popconfirm.css +1 -1
  160. package/lib/es/popover/popover.css +1 -1
  161. package/lib/es/radio/radio.css +2 -2
  162. package/lib/es/scrollList/itemFoundation.js +12 -0
  163. package/lib/es/scrollList/scrollList.css +2 -2
  164. package/lib/es/select/foundation.d.ts +1 -1
  165. package/lib/es/select/foundation.js +28 -2
  166. package/lib/es/select/select.css +6 -6
  167. package/lib/es/sideSheet/sideSheet.css +2 -2
  168. package/lib/es/sidebar/sidebar.css +11 -11
  169. package/lib/es/slider/foundation.js +46 -12
  170. package/lib/es/slider/rtl.scss +62 -0
  171. package/lib/es/slider/slider.css +45 -0
  172. package/lib/es/slider/slider.scss +2 -0
  173. package/lib/es/steps/steps.css +11 -11
  174. package/lib/es/switch/switch.css +1 -0
  175. package/lib/es/switch/switch.scss +1 -0
  176. package/lib/es/switch/variables.scss +2 -1
  177. package/lib/es/table/foundation.d.ts +36 -0
  178. package/lib/es/table/foundation.js +164 -29
  179. package/lib/es/table/table.css +10 -2
  180. package/lib/es/table/table.scss +17 -0
  181. package/lib/es/tabs/tabs.css +2 -2
  182. package/lib/es/tag/tag.css +28 -2
  183. package/lib/es/tag/tag.scss +33 -0
  184. package/lib/es/tagInput/tagInput.css +19 -2
  185. package/lib/es/tagInput/tagInput.scss +18 -0
  186. package/lib/es/timePicker/constants.d.ts +1 -0
  187. package/lib/es/timePicker/foundation.d.ts +7 -1
  188. package/lib/es/timePicker/foundation.js +62 -11
  189. package/lib/es/timePicker/timePicker.css +1 -1
  190. package/lib/es/timeline/timeline.css +2 -2
  191. package/lib/es/toast/toast.css +1 -1
  192. package/lib/es/tooltip/foundation.js +8 -5
  193. package/lib/es/tooltip/tooltip.css +1 -1
  194. package/lib/es/transfer/constants.d.ts +3 -1
  195. package/lib/es/transfer/constants.js +3 -1
  196. package/lib/es/transfer/foundation.d.ts +3 -0
  197. package/lib/es/transfer/foundation.js +4 -0
  198. package/lib/es/transfer/transfer.css +14 -5
  199. package/lib/es/transfer/transfer.scss +10 -0
  200. package/lib/es/tree/foundation.d.ts +3 -0
  201. package/lib/es/tree/foundation.js +31 -4
  202. package/lib/es/tree/tree.css +1 -1
  203. package/lib/es/treeSelect/foundation.d.ts +1 -0
  204. package/lib/es/treeSelect/foundation.js +8 -1
  205. package/lib/es/treeSelect/treeSelect.css +36 -4
  206. package/lib/es/treeSelect/treeSelect.scss +49 -1
  207. package/lib/es/typography/typography.css +8 -8
  208. package/lib/es/upload/upload.css +8 -8
  209. package/lib/es/utils/Store.d.ts +1 -1
  210. package/lib/es/utils/Store.js +1 -0
  211. package/navigation/navigation.scss +1 -0
  212. package/navigation/variables.scss +1 -1
  213. package/overflowList/foundation.ts +48 -2
  214. package/package.json +19 -4
  215. package/scrollList/itemFoundation.ts +12 -0
  216. package/select/foundation.ts +27 -2
  217. package/slider/foundation.ts +55 -15
  218. package/slider/rtl.scss +62 -0
  219. package/slider/slider.scss +2 -0
  220. package/switch/switch.scss +1 -0
  221. package/switch/variables.scss +2 -1
  222. package/table/foundation.ts +199 -30
  223. package/table/table.scss +17 -0
  224. package/tag/tag.scss +33 -0
  225. package/tagInput/tagInput.scss +18 -0
  226. package/timePicker/constants.ts +2 -0
  227. package/timePicker/foundation.ts +62 -10
  228. package/tooltip/foundation.ts +8 -5
  229. package/transfer/constants.ts +3 -1
  230. package/transfer/foundation.ts +8 -1
  231. package/transfer/transfer.scss +10 -0
  232. package/tree/foundation.ts +34 -5
  233. package/treeSelect/foundation.ts +10 -1
  234. package/treeSelect/treeSelect.scss +49 -1
  235. package/utils/Store.ts +2 -1
@@ -28,22 +28,66 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
28
28
 
29
29
  getOverflowItem(): Array<Array<Record<string, any>>> {
30
30
  const { items } = this.getProps();
31
- const { visibleState, overflow } = this.getStates();
31
+ const { visibleState, overflow, scrollOverflow } = this.getStates();
32
32
  if (!this.isScrollMode()) {
33
33
  return overflow;
34
34
  }
35
35
 
36
+ // Scroll mode relies on IntersectionObserver to compute visibility.
37
+ // During recalculation (e.g. items changed, or before observer fires),
38
+ // keep last computed overflow to avoid UI flicker (tabs arrows/menu state).
39
+ if (!visibleState || visibleState.size === 0) {
40
+ if (Array.isArray(scrollOverflow) && scrollOverflow.length === 2) {
41
+ return scrollOverflow;
42
+ }
43
+ return [[], []];
44
+ }
36
45
 
37
46
  const visibleStateArr = items.map(({ key }: { key: string }) => Boolean(visibleState.get(key)));
38
47
  const visibleStart = visibleStateArr.indexOf(true);
39
48
  const visibleEnd = visibleStateArr.lastIndexOf(true);
40
49
 
50
+ // If no item is visible (e.g. initial layout not ready or list out of viewport),
51
+ // treat it as "unknown" and keep last computed overflow to avoid wrong enabling.
52
+ if (visibleStart < 0 || visibleEnd < 0) {
53
+ if (Array.isArray(scrollOverflow) && scrollOverflow.length === 2) {
54
+ return scrollOverflow;
55
+ }
56
+ return [[], []];
57
+ }
58
+
41
59
  const overflowList = [];
42
60
  overflowList[0] = visibleStart >= 0 ? items.slice(0, visibleStart) : [];
43
61
  overflowList[1] = visibleEnd >= 0 ? items.slice(visibleEnd + 1, items.length) : items.slice();
44
62
  return overflowList;
45
63
  }
46
64
 
65
+ private _syncScrollOverflowCache(nextVisibleState: Map<string, boolean>): void {
66
+ if (!this.isScrollMode()) {
67
+ return;
68
+ }
69
+ const { items } = this.getProps();
70
+ const visibleStateArr = items.map(({ key }: { key: string }) => Boolean(nextVisibleState.get(key)));
71
+ const visibleStart = visibleStateArr.indexOf(true);
72
+ const visibleEnd = visibleStateArr.lastIndexOf(true);
73
+
74
+ // No visible items means the result is not reliable; keep cache and stay "calculating"
75
+ if (visibleStart < 0 || visibleEnd < 0) {
76
+ this._adapter.updateStates({
77
+ isScrollOverflowCalculating: true,
78
+ });
79
+ return;
80
+ }
81
+
82
+ const overflowList: Array<Array<Record<string, any>>> = [];
83
+ overflowList[0] = visibleStart >= 0 ? items.slice(0, visibleStart) : [];
84
+ overflowList[1] = visibleEnd >= 0 ? items.slice(visibleEnd + 1, items.length) : items.slice();
85
+ this._adapter.updateStates({
86
+ scrollOverflow: overflowList,
87
+ isScrollOverflowCalculating: false,
88
+ });
89
+ }
90
+
47
91
  handleIntersect(entries: Array<IntersectionObserverEntry>): void {
48
92
  const visibleState = copy(this.getState('visibleState'));
49
93
 
@@ -73,6 +117,8 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
73
117
  }
74
118
  this.previousY = currentY;
75
119
  this._adapter.updateVisibleState(visibleState);
120
+ // Keep scroll overflow cache in sync for stable UI
121
+ this._syncScrollOverflowCache(visibleState);
76
122
  this._adapter.notifyIntersect(res);
77
123
  }
78
124
 
@@ -126,4 +172,4 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
126
172
 
127
173
  }
128
174
 
129
- export default OverflowListFoundation;
175
+ export default OverflowListFoundation;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.96.1",
3
+ "version": "2.98.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "clean": "rimraf lib",
@@ -10053,6 +10053,21 @@
10053
10053
  "import": "./lib/es/slider/foundation.js",
10054
10054
  "require": "./lib/cjs/slider/foundation.js"
10055
10055
  },
10056
+ "./lib/es/slider/rtl.scss": {
10057
+ "import": "./lib/es/slider/rtl.scss",
10058
+ "require": "./lib/cjs/slider/rtl.scss",
10059
+ "default": "./lib/es/slider/rtl.scss"
10060
+ },
10061
+ "./lib/cjs/slider/rtl.scss": {
10062
+ "import": "./lib/es/slider/rtl.scss",
10063
+ "require": "./lib/cjs/slider/rtl.scss",
10064
+ "default": "./lib/es/slider/rtl.scss"
10065
+ },
10066
+ "./slider/rtl.scss": {
10067
+ "import": "./lib/es/slider/rtl.scss",
10068
+ "require": "./lib/cjs/slider/rtl.scss",
10069
+ "default": "./lib/es/slider/rtl.scss"
10070
+ },
10056
10071
  "./lib/es/slider/slider.css": {
10057
10072
  "import": "./lib/es/slider/slider.css",
10058
10073
  "require": "./lib/cjs/slider/slider.css",
@@ -14210,8 +14225,8 @@
14210
14225
  }
14211
14226
  },
14212
14227
  "dependencies": {
14213
- "@douyinfe/semi-animation": "2.96.1",
14214
- "@douyinfe/semi-json-viewer-core": "2.96.1",
14228
+ "@douyinfe/semi-animation": "2.98.0",
14229
+ "@douyinfe/semi-json-viewer-core": "2.98.0",
14215
14230
  "@mdx-js/mdx": "^3.0.1",
14216
14231
  "async-validator": "^3.5.0",
14217
14232
  "classnames": "^2.2.6",
@@ -14232,7 +14247,7 @@
14232
14247
  "*.scss",
14233
14248
  "*.css"
14234
14249
  ],
14235
- "gitHead": "c2077bb9f3ac194ef162fa6b8332a3997c83d041",
14250
+ "gitHead": "e33a947a4e0745a7ad15d3e773355cc19d23b174",
14236
14251
  "devDependencies": {
14237
14252
  "@babel/plugin-transform-runtime": "^7.15.8",
14238
14253
  "@babel/preset-env": "^7.15.8",
@@ -91,6 +91,12 @@ export default class ItemFoundation<P = Record<string, any>, S = Record<string,
91
91
  const lastRect = lastNode.getBoundingClientRect();
92
92
 
93
93
  const listHeight = lastRect.height * list.length;
94
+ // Guard against environments where layout is not computed
95
+ // (e.g. jsdom returns all-zero rects), which would otherwise
96
+ // make `baseTop += listHeight` a no-op and loop forever.
97
+ if (listHeight <= 0) {
98
+ return 0;
99
+ }
94
100
  let baseTop = lastRect.top;
95
101
  let count = 0;
96
102
 
@@ -127,6 +133,12 @@ export default class ItemFoundation<P = Record<string, any>, S = Record<string,
127
133
  const firstRect = firstNode.getBoundingClientRect();
128
134
 
129
135
  const listHeight = firstRect.height * list.length;
136
+ // Guard against environments where layout is not computed
137
+ // (e.g. jsdom returns all-zero rects), which would otherwise
138
+ // make `baseTop -= listHeight` a no-op and loop forever.
139
+ if (listHeight <= 0) {
140
+ return 0;
141
+ }
130
142
 
131
143
  let baseTop = firstRect.top;
132
144
  let count = 0;
@@ -85,15 +85,39 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
85
85
  }
86
86
  }
87
87
 
88
- focus(optionsForOpen?: BasicOptionProps[]) {
88
+ focus(optionsForOpen?: BasicOptionProps[], openDropdown?: boolean) {
89
89
  const isFilterable = this._isFilterable();
90
90
  const isMultiple = this._isMultiple();
91
91
  const { isOpen } = this.getStates();
92
+ const { searchPosition } = this.getProps();
93
+ // Default to true if not specified (backward compatibility)
94
+ const shouldOpenDropdown = openDropdown !== false;
92
95
 
93
96
  this._adapter.updateFocusState(true);
94
97
  this._adapter.setIsFocusInContainer(false);
95
98
 
96
99
  if (isFilterable) {
100
+ /**
101
+ * When openDropdown is false, we only want to "refocus" the Select
102
+ * without changing dropdown visibility.
103
+ *
104
+ * NOTE: For searchPosition='dropdown', the search input is rendered in dropdown,
105
+ * so we should NOT toggle trigger input(showInput) here, otherwise it may affect
106
+ * tabIndex / focusability unexpectedly.
107
+ */
108
+ if (!shouldOpenDropdown) {
109
+ if (searchPosition === strings.SEARCH_POSITION_TRIGGER) {
110
+ if (isMultiple) {
111
+ this.focusInput();
112
+ } else {
113
+ this.toggle2SearchInput(true);
114
+ }
115
+ } else {
116
+ this._focusTrigger();
117
+ }
118
+ return;
119
+ }
120
+
97
121
  if (isMultiple) {
98
122
  // when filter and multiple, focus input and open dropdown
99
123
  this.focusInput();
@@ -1077,7 +1101,8 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
1077
1101
  this.clearInput(e);
1078
1102
  }
1079
1103
  // after click showClear button, the select need to be focused
1080
- this.focus();
1104
+ // but don't open dropdown to avoid focus state confusion
1105
+ this.focus(undefined, false);
1081
1106
  this.clearSelected();
1082
1107
  // prevent this click open dropdown
1083
1108
  e.stopPropagation();
@@ -147,6 +147,8 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
147
147
  getMinAndMaxPercent = (value: number | number[]) => {
148
148
  // debugger
149
149
  const { range, min, max } = this._adapter.getProps();
150
+ // Percent always increases with value, independent of visual direction.
151
+ // UI layer decides whether to use `left` or `right` to place elements.
150
152
  const minPercent = range ? (value[0] - min) / (max - min) : (value as number - min) / (max - min);
151
153
  const maxPercent = range ? (value[1] - min) / (max - min) : 1;
152
154
  return { min: this._checkValidity(minPercent), max: this._checkValidity(maxPercent) };
@@ -264,6 +266,8 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
264
266
 
265
267
  // Returns the length of the distance to the left
266
268
  const { vertical, verticalReverse, range } = this._adapter.getProps();
269
+ const direction = this._adapter.getContext('direction');
270
+ const isRTL = direction === 'rtl' && !vertical;
267
271
  const value = this._adapter.getState('currentValue');
268
272
  const currentPos = this.transValueToPos(value);
269
273
  const { sliderX, sliderY, sliderWidth, sliderHeight } = this._adapter.getSliderLengths();
@@ -272,6 +276,9 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
272
276
  let startPos;
273
277
  if (vertical && verticalReverse) {
274
278
  startPos = sliderY + len;
279
+ } else if (isRTL) {
280
+ // In RTL mode, start from right (sliderX + sliderWidth)
281
+ startPos = sliderX + len;
275
282
  } else {
276
283
  startPos = vertical ? sliderY : sliderX;
277
284
  }
@@ -279,13 +286,16 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
279
286
  let endPos;
280
287
  if (vertical && verticalReverse) {
281
288
  endPos = sliderY;
289
+ } else if (isRTL) {
290
+ // In RTL mode, end at left (sliderX)
291
+ endPos = sliderX;
282
292
  } else {
283
293
  endPos = vertical ? sliderY + sliderHeight : sliderX + sliderWidth;
284
294
  }
285
295
  // endPos = chooseMovePos === 'min' && isDrag && range ? currentPos[1] : endPos;
286
296
 
287
297
 
288
- if (vertical && verticalReverse) {
298
+ if ((vertical && verticalReverse) || isRTL) {
289
299
  if (position >= startPos) {
290
300
  position = startPos;
291
301
  } else if (position <= endPos) {
@@ -310,6 +320,8 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
310
320
  const pos = this.checkMeetMinMax(mousePos);
311
321
  const { min, max, currentValue } = this._adapter.getStates();
312
322
  const { range, vertical, step, verticalReverse } = this._adapter.getProps();
323
+ const direction = this._adapter.getContext('direction');
324
+ const isRTL = direction === 'rtl' && !vertical;
313
325
  const { sliderX, sliderY, sliderWidth, sliderHeight } = this._adapter.getSliderLengths();
314
326
  const startPos = vertical ? sliderY : sliderX;
315
327
  const len = vertical ? sliderHeight : sliderWidth;
@@ -317,6 +329,9 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
317
329
  if (vertical && verticalReverse) {
318
330
  //isMin = !isMin;
319
331
  stepValue = ((startPos + len - pos) / len) * (max - min) + min;
332
+ } else if (isRTL) {
333
+ // In RTL mode, position is calculated from right to left
334
+ stepValue = ((startPos + len - pos) / len) * (max - min) + min;
320
335
  } else {
321
336
  stepValue = ((pos - startPos) / len) * (max - min) + min;
322
337
  }
@@ -347,13 +362,29 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
347
362
  transValueToPos = (value: SliderProps['value']) => {
348
363
  const { min, max } = this._adapter.getStates();
349
364
  const { vertical, range, verticalReverse } = this._adapter.getProps();
365
+ const direction = this._adapter.getContext('direction');
366
+ const isRTL = direction === 'rtl' && !vertical;
350
367
  const { sliderX, sliderY, sliderWidth, sliderHeight } = this._adapter.getSliderLengths();
368
+
351
369
  const startPos = vertical ? sliderY : sliderX;
352
370
  const len = vertical ? sliderHeight : sliderWidth;
371
+
372
+ const transSingle = (val: number) => {
373
+ const percent = (val - min) / (max - min);
374
+ if (vertical && verticalReverse) {
375
+ // Reverse direction in vertical mode
376
+ return startPos + len - percent * len;
377
+ }
378
+ if (isRTL) {
379
+ // Reverse direction in horizontal RTL
380
+ return startPos + len - percent * len;
381
+ }
382
+ return startPos + percent * len;
383
+ };
353
384
  if (range) {
354
- return [((value[0] - min) * len) / (max - min) + startPos, ((value[1] - min) * len) / (max - min) + startPos];
385
+ return [transSingle(value[0]), transSingle(value[1])];
355
386
  } else {
356
- return ((value as number - min) * len) / (max - min) + startPos;
387
+ return transSingle(value as number);
357
388
  }
358
389
  };
359
390
 
@@ -649,22 +680,34 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
649
680
 
650
681
  handleKeyDown = (event: any, handler: 'min'| 'max') => {
651
682
  const { min, max, currentValue } = this.getStates();
652
- const { step, range } = this.getProps();
683
+ const { step, range, vertical } = this.getProps();
684
+ const direction = this._adapter.getContext('direction');
685
+ const isRTL = direction === 'rtl' && !vertical;
653
686
  let outputValue;
654
687
  switch (event.key) {
655
688
  case "ArrowLeft":
656
689
  case "ArrowDown":
657
- outputValue = this._handleValueDecreaseWithKeyBoard(step, handler);
690
+ // In RTL mode, ArrowLeft and ArrowDown should increase value
691
+ outputValue = isRTL ?
692
+ this._handleValueIncreaseWithKeyBoard(step, handler) :
693
+ this._handleValueDecreaseWithKeyBoard(step, handler);
658
694
  break;
659
695
  case "ArrowRight":
660
696
  case "ArrowUp":
661
- outputValue = this._handleValueIncreaseWithKeyBoard(step, handler);
697
+ // In RTL mode, ArrowRight and ArrowUp should decrease value
698
+ outputValue = isRTL ?
699
+ this._handleValueDecreaseWithKeyBoard(step, handler) :
700
+ this._handleValueIncreaseWithKeyBoard(step, handler);
662
701
  break;
663
702
  case "PageUp":
664
- outputValue = this._handleValueIncreaseWithKeyBoard(10 * step, handler);
703
+ outputValue = isRTL ?
704
+ this._handleValueDecreaseWithKeyBoard(10 * step, handler) :
705
+ this._handleValueIncreaseWithKeyBoard(10 * step, handler);
665
706
  break;
666
707
  case "PageDown":
667
- outputValue = this._handleValueDecreaseWithKeyBoard(10 * step, handler);
708
+ outputValue = isRTL ?
709
+ this._handleValueIncreaseWithKeyBoard(10 * step, handler) :
710
+ this._handleValueDecreaseWithKeyBoard(10 * step, handler);
668
711
  break;
669
712
  case "Home":
670
713
  outputValue = this._handleHomeKey(handler);
@@ -775,13 +818,10 @@ export default class SliderFoundation extends BaseFoundation<SliderAdapter> {
775
818
  const currentPos = this.transValueToPos(currentValue);
776
819
  let isMin = true;
777
820
  if (Array.isArray(currentPos)) {
778
- // Slide on both sides
779
- if (
780
- pagePos > currentPos[1] ||
781
- Math.abs(pagePos - currentPos[0]) > Math.abs(pagePos - currentPos[1])
782
- ) {
783
- isMin = false;
784
- }
821
+ // Choose the nearest handle regardless of ordering (LTR/RTL/verticalReverse)
822
+ const distToFirst = Math.abs(pagePos - currentPos[0]);
823
+ const distToSecond = Math.abs(pagePos - currentPos[1]);
824
+ isMin = distToFirst <= distToSecond;
785
825
  }
786
826
  if (vertical && verticalReverse) {
787
827
  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
+ }
@@ -252,3 +252,5 @@ $module: #{$prefix}-slider;
252
252
  .#{$module}-reverse {
253
253
  transform: rotate(180deg);
254
254
  }
255
+
256
+ @import "./rtl.scss";
@@ -43,6 +43,7 @@ $module: #{$prefix}-switch;
43
43
 
44
44
  .#{$module}-knob {
45
45
  transform: translateX($spacing-switch_checked-translateX);
46
+ background-color: $color-switch_knob-bg-checked;
46
47
  }
47
48
 
48
49
  &:active {
@@ -30,7 +30,8 @@ $color-switch_disabled-border-default: var(--semi-color-border); // 禁用态开
30
30
  $color-switch_disabled-bg-hover: transparent; // 禁用态开关背景色 - 悬浮
31
31
  $color-switch_checked_disabled-bg-default: var(--semi-color-success-disabled); // 禁用开启态开关背景颜色
32
32
  $color-switch_checked_disabled-border-default: transparent; // 禁用开启态开关描边颜色
33
- $color-switch_knob-bg-default: rgba(var(--semi-white), 1); // 开关滑块背景颜色
33
+ $color-switch_knob-bg-default: rgba(var(--semi-white), 1); // 开关滑块背景颜色 - 关闭态
34
+ $color-switch_knob-bg-checked: rgba(var(--semi-white), 1); // 开关滑块背景颜色 - 开启态
34
35
  $color-switch_knob-border-default: var(--semi-color-border); // 开关滑块描边颜色
35
36
  $color-switch_checked-text-default: var(--semi-color-white); // 开启态开关文案颜色
36
37
  $color-switch_unchecked-text-default: var(--semi-color-text-2); // 关闭态开关文案颜色