@teamix-evo/ui 0.4.0 → 0.5.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 (511) hide show
  1. package/README.md +46 -50
  2. package/manifest.json +406 -653
  3. package/package.json +15 -34
  4. package/src/_design-system/theme-tokens/stories.tsx +1474 -0
  5. package/src/components/accordion/index.tsx +139 -0
  6. package/src/components/accordion/meta.md +162 -0
  7. package/src/components/accordion/stories.tsx +145 -0
  8. package/src/components/affix/index.tsx +149 -0
  9. package/src/components/affix/meta.md +23 -0
  10. package/src/components/affix/stories.tsx +70 -0
  11. package/src/components/alert/index.tsx +220 -0
  12. package/src/components/alert/meta.md +133 -0
  13. package/src/components/alert/stories.tsx +126 -0
  14. package/src/components/alert-dialog/index.tsx +282 -0
  15. package/src/components/alert-dialog/meta.md +86 -0
  16. package/src/components/alert-dialog/stories.tsx +163 -0
  17. package/src/components/avatar/index.tsx +159 -0
  18. package/src/components/avatar/meta.md +242 -0
  19. package/src/components/avatar/stories.tsx +241 -0
  20. package/src/components/badge/index.tsx +299 -0
  21. package/src/components/badge/meta.md +237 -0
  22. package/src/components/badge/stories.tsx +275 -0
  23. package/src/components/breadcrumb/index.tsx +137 -0
  24. package/src/components/breadcrumb/meta.md +64 -0
  25. package/src/components/breadcrumb/stories.tsx +86 -0
  26. package/src/components/button/index.tsx +202 -0
  27. package/src/components/button/meta.md +209 -0
  28. package/src/components/button/stories.tsx +215 -0
  29. package/src/components/button-group/index.tsx +211 -0
  30. package/src/components/button-group/meta.md +190 -0
  31. package/src/components/button-group/stories.tsx +182 -0
  32. package/src/components/calendar/index.tsx +240 -0
  33. package/src/components/calendar/meta.md +36 -0
  34. package/src/components/calendar/stories.tsx +36 -0
  35. package/src/components/card/index.tsx +262 -0
  36. package/src/components/card/meta.md +194 -0
  37. package/src/components/card/stories.tsx +202 -0
  38. package/src/components/carousel/index.tsx +481 -0
  39. package/src/components/carousel/meta.md +208 -0
  40. package/src/components/carousel/stories.tsx +271 -0
  41. package/src/components/cascader-select/index.tsx +308 -0
  42. package/src/components/cascader-select/meta.md +28 -0
  43. package/src/components/cascader-select/stories.tsx +118 -0
  44. package/src/components/checkbox/index.tsx +208 -0
  45. package/src/components/checkbox/meta.md +166 -0
  46. package/src/components/checkbox/stories.tsx +206 -0
  47. package/src/components/collapsible/index.tsx +72 -0
  48. package/src/components/collapsible/meta.md +87 -0
  49. package/src/components/collapsible/stories.tsx +97 -0
  50. package/src/components/color-picker/index.tsx +677 -0
  51. package/src/components/color-picker/meta.md +83 -0
  52. package/src/components/color-picker/stories.tsx +172 -0
  53. package/src/components/combobox/index.tsx +687 -0
  54. package/src/components/combobox/meta.md +83 -0
  55. package/src/components/combobox/stories.tsx +179 -0
  56. package/src/components/command/index.tsx +238 -0
  57. package/src/components/command/meta.md +48 -0
  58. package/src/components/command/stories.tsx +83 -0
  59. package/src/components/data-table/index.tsx +1537 -0
  60. package/src/components/data-table/meta.md +107 -0
  61. package/src/components/data-table/stories.tsx +1234 -0
  62. package/src/components/date-picker/index.tsx +1492 -0
  63. package/src/components/date-picker/meta.md +103 -0
  64. package/src/components/date-picker/stories.tsx +125 -0
  65. package/src/components/descriptions/index.tsx +535 -0
  66. package/src/components/descriptions/meta.md +104 -0
  67. package/src/components/descriptions/stories.tsx +389 -0
  68. package/src/components/dialog/index.tsx +255 -0
  69. package/src/components/dialog/meta.md +244 -0
  70. package/src/components/dialog/stories.tsx +330 -0
  71. package/src/components/dropdown-menu/index.tsx +301 -0
  72. package/src/components/dropdown-menu/meta.md +93 -0
  73. package/src/components/dropdown-menu/stories.tsx +124 -0
  74. package/src/components/empty/index.tsx +431 -0
  75. package/src/components/empty/meta.md +274 -0
  76. package/src/components/empty/stories.tsx +278 -0
  77. package/src/components/field/index.tsx +374 -0
  78. package/src/components/field/meta.md +283 -0
  79. package/src/components/field/stories.tsx +327 -0
  80. package/src/components/filter-bar/index.tsx +976 -0
  81. package/src/components/filter-bar/meta.md +57 -0
  82. package/src/components/filter-bar/stories.tsx +496 -0
  83. package/src/components/float-button/index.tsx +163 -0
  84. package/src/components/float-button/meta.md +73 -0
  85. package/src/components/float-button/stories.tsx +68 -0
  86. package/src/components/form/index.tsx +218 -0
  87. package/src/components/form/meta.md +16 -0
  88. package/src/components/form/stories.tsx +301 -0
  89. package/src/components/hover-card/index.tsx +103 -0
  90. package/src/components/hover-card/meta.md +71 -0
  91. package/src/components/hover-card/stories.tsx +107 -0
  92. package/src/components/icon/index.tsx +225 -0
  93. package/src/components/icon/meta.md +102 -0
  94. package/src/components/icon/stories.tsx +127 -0
  95. package/src/components/image/index.tsx +147 -0
  96. package/src/components/image/meta.md +55 -0
  97. package/src/components/image/stories.tsx +48 -0
  98. package/src/components/input/index.tsx +63 -0
  99. package/src/components/input/meta.md +57 -0
  100. package/src/components/input/stories.tsx +66 -0
  101. package/src/components/input-group/index.tsx +292 -0
  102. package/src/components/input-group/meta.md +108 -0
  103. package/src/components/input-group/stories.tsx +258 -0
  104. package/src/components/input-ip/index.tsx +288 -0
  105. package/src/components/input-ip/meta.md +48 -0
  106. package/src/components/input-ip/stories.tsx +69 -0
  107. package/src/components/input-number/index.tsx +360 -0
  108. package/src/components/input-number/meta.md +156 -0
  109. package/src/components/input-number/stories.tsx +187 -0
  110. package/src/components/item/index.tsx +368 -0
  111. package/src/components/item/meta.md +395 -0
  112. package/src/components/item/stories.tsx +432 -0
  113. package/src/components/label/index.tsx +44 -0
  114. package/src/components/label/meta.md +68 -0
  115. package/src/components/label/stories.tsx +64 -0
  116. package/src/components/mentions/index.tsx +369 -0
  117. package/src/components/mentions/meta.md +118 -0
  118. package/src/components/mentions/stories.tsx +153 -0
  119. package/src/components/menubar/index.tsx +313 -0
  120. package/src/components/menubar/meta.md +52 -0
  121. package/src/components/menubar/stories.tsx +99 -0
  122. package/src/components/navigation-menu/index.tsx +216 -0
  123. package/src/components/navigation-menu/meta.md +66 -0
  124. package/src/components/navigation-menu/stories.tsx +137 -0
  125. package/src/components/page-header/index.tsx +218 -0
  126. package/src/components/page-header/meta.md +211 -0
  127. package/src/components/page-header/stories.tsx +290 -0
  128. package/src/components/page-shell/index.tsx +119 -0
  129. package/src/components/page-shell/meta.md +115 -0
  130. package/src/components/page-shell/stories.tsx +154 -0
  131. package/src/components/pagination/index.tsx +580 -0
  132. package/src/components/pagination/meta.md +39 -0
  133. package/src/components/pagination/stories.tsx +319 -0
  134. package/src/components/popconfirm/index.tsx +477 -0
  135. package/src/components/popconfirm/meta.md +164 -0
  136. package/src/components/popconfirm/stories.tsx +231 -0
  137. package/src/components/popover/index.tsx +181 -0
  138. package/src/components/popover/meta.md +97 -0
  139. package/src/components/popover/stories.tsx +169 -0
  140. package/src/components/progress/index.tsx +176 -0
  141. package/src/components/progress/meta.md +95 -0
  142. package/src/components/progress/stories.tsx +115 -0
  143. package/src/components/radio-group/index.tsx +78 -0
  144. package/src/components/radio-group/meta.md +137 -0
  145. package/src/components/radio-group/stories.tsx +285 -0
  146. package/src/components/rate/index.tsx +284 -0
  147. package/src/components/rate/meta.md +63 -0
  148. package/src/components/rate/stories.tsx +107 -0
  149. package/src/components/resizable/index.tsx +122 -0
  150. package/src/components/resizable/meta.md +142 -0
  151. package/src/components/resizable/stories.tsx +105 -0
  152. package/src/components/scroll-area/index.tsx +83 -0
  153. package/src/components/scroll-area/meta.md +85 -0
  154. package/src/components/scroll-area/stories.tsx +82 -0
  155. package/src/components/select/index.tsx +325 -0
  156. package/src/components/select/meta.md +183 -0
  157. package/src/components/select/stories.tsx +210 -0
  158. package/src/components/separator/index.tsx +51 -0
  159. package/src/components/separator/meta.md +68 -0
  160. package/src/components/separator/stories.tsx +53 -0
  161. package/src/components/sheet/index.tsx +293 -0
  162. package/src/components/sheet/meta.md +226 -0
  163. package/src/components/sheet/stories.tsx +405 -0
  164. package/src/components/sidebar/index.tsx +715 -0
  165. package/src/components/sidebar/meta.md +14 -0
  166. package/src/components/sidebar/{sidebar.stories.tsx → stories.tsx} +250 -330
  167. package/src/components/skeleton/index.tsx +415 -0
  168. package/src/components/skeleton/meta.md +210 -0
  169. package/src/components/skeleton/stories.tsx +197 -0
  170. package/src/components/slider/index.tsx +222 -0
  171. package/src/components/slider/meta.md +125 -0
  172. package/src/components/slider/stories.tsx +109 -0
  173. package/src/components/sonner/index.tsx +149 -0
  174. package/src/components/sonner/meta.md +156 -0
  175. package/src/components/sonner/stories.tsx +285 -0
  176. package/src/components/spinner/index.tsx +335 -0
  177. package/src/components/spinner/meta.md +172 -0
  178. package/src/components/spinner/stories.tsx +197 -0
  179. package/src/components/statistic/{statistic.tsx → index.tsx} +25 -26
  180. package/src/components/statistic/meta.md +94 -0
  181. package/src/components/statistic/stories.tsx +85 -0
  182. package/src/components/steps/index.tsx +500 -0
  183. package/src/components/steps/meta.md +245 -0
  184. package/src/components/steps/stories.tsx +287 -0
  185. package/src/components/switch/index.tsx +175 -0
  186. package/src/components/switch/meta.md +107 -0
  187. package/src/components/switch/stories.tsx +154 -0
  188. package/src/components/table/index.tsx +350 -0
  189. package/src/components/table/meta.md +148 -0
  190. package/src/components/table/stories.tsx +189 -0
  191. package/src/components/tabs/index.tsx +379 -0
  192. package/src/components/tabs/meta.md +244 -0
  193. package/src/components/tabs/stories.tsx +312 -0
  194. package/src/components/tag/index.tsx +774 -0
  195. package/src/components/tag/meta.md +256 -0
  196. package/src/components/tag/stories.tsx +431 -0
  197. package/src/components/textarea/index.tsx +62 -0
  198. package/src/components/textarea/meta.md +77 -0
  199. package/src/components/textarea/stories.tsx +112 -0
  200. package/src/components/time-picker/index.tsx +887 -0
  201. package/src/components/time-picker/meta.md +102 -0
  202. package/src/components/time-picker/stories.tsx +125 -0
  203. package/src/components/timeline/index.tsx +422 -0
  204. package/src/components/timeline/meta.md +352 -0
  205. package/src/components/timeline/stories.tsx +369 -0
  206. package/src/components/toggle/index.tsx +74 -0
  207. package/src/components/toggle/meta.md +76 -0
  208. package/src/components/toggle/stories.tsx +66 -0
  209. package/src/components/toggle-group/index.tsx +167 -0
  210. package/src/components/toggle-group/meta.md +141 -0
  211. package/src/components/toggle-group/stories.tsx +124 -0
  212. package/src/components/tooltip/index.tsx +144 -0
  213. package/src/components/tooltip/meta.md +186 -0
  214. package/src/components/tooltip/stories.tsx +212 -0
  215. package/src/components/transfer/index.tsx +639 -0
  216. package/src/components/transfer/meta.md +76 -0
  217. package/src/components/transfer/stories.tsx +221 -0
  218. package/src/components/tree/index.tsx +764 -0
  219. package/src/components/tree/meta.md +96 -0
  220. package/src/components/tree/stories.tsx +385 -0
  221. package/src/components/tree/utils.ts +269 -0
  222. package/src/components/tree-select/index.tsx +400 -0
  223. package/src/components/tree-select/meta.md +78 -0
  224. package/src/components/tree-select/stories.tsx +234 -0
  225. package/src/components/typography/index.tsx +290 -0
  226. package/src/components/typography/meta.md +151 -0
  227. package/src/components/typography/stories.tsx +151 -0
  228. package/src/components/upload/index.tsx +858 -0
  229. package/src/components/upload/meta.md +122 -0
  230. package/src/components/upload/stories.tsx +261 -0
  231. package/src/components/watermark/index.tsx +152 -0
  232. package/src/components/watermark/meta.md +67 -0
  233. package/src/components/watermark/stories.tsx +59 -0
  234. package/src/hooks/use-mobile.ts +9 -11
  235. package/src/lib/color.ts +243 -0
  236. package/src/{utils/cn.ts → lib/utils.ts} +1 -1
  237. package/src/components/accordion/accordion.meta.md +0 -88
  238. package/src/components/accordion/accordion.stories.tsx +0 -72
  239. package/src/components/accordion/accordion.tsx +0 -154
  240. package/src/components/affix/affix.meta.md +0 -98
  241. package/src/components/affix/affix.stories.tsx +0 -134
  242. package/src/components/affix/affix.tsx +0 -167
  243. package/src/components/alert/alert.meta.md +0 -132
  244. package/src/components/alert/alert.stories.tsx +0 -138
  245. package/src/components/alert/alert.tsx +0 -179
  246. package/src/components/alert-dialog/alert-dialog.meta.md +0 -152
  247. package/src/components/alert-dialog/alert-dialog.stories.tsx +0 -223
  248. package/src/components/alert-dialog/alert-dialog.tsx +0 -183
  249. package/src/components/anchor/anchor.meta.md +0 -92
  250. package/src/components/anchor/anchor.stories.tsx +0 -74
  251. package/src/components/anchor/anchor.tsx +0 -130
  252. package/src/components/app/app.meta.md +0 -91
  253. package/src/components/app/app.stories.tsx +0 -64
  254. package/src/components/app/app.tsx +0 -58
  255. package/src/components/aspect-ratio/aspect-ratio.meta.md +0 -82
  256. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +0 -59
  257. package/src/components/aspect-ratio/aspect-ratio.tsx +0 -22
  258. package/src/components/auto-complete/auto-complete.meta.md +0 -110
  259. package/src/components/auto-complete/auto-complete.stories.tsx +0 -136
  260. package/src/components/auto-complete/auto-complete.tsx +0 -253
  261. package/src/components/avatar/avatar.meta.md +0 -93
  262. package/src/components/avatar/avatar.stories.tsx +0 -98
  263. package/src/components/avatar/avatar.tsx +0 -127
  264. package/src/components/badge/badge.meta.md +0 -120
  265. package/src/components/badge/badge.stories.tsx +0 -153
  266. package/src/components/badge/badge.tsx +0 -204
  267. package/src/components/breadcrumb/breadcrumb.meta.md +0 -127
  268. package/src/components/breadcrumb/breadcrumb.stories.tsx +0 -207
  269. package/src/components/breadcrumb/breadcrumb.tsx +0 -136
  270. package/src/components/button/button.meta.md +0 -335
  271. package/src/components/button/button.stories.tsx +0 -743
  272. package/src/components/button/button.tsx +0 -466
  273. package/src/components/calendar/calendar.meta.md +0 -128
  274. package/src/components/calendar/calendar.stories.tsx +0 -68
  275. package/src/components/calendar/calendar.tsx +0 -172
  276. package/src/components/card/card.meta.md +0 -139
  277. package/src/components/card/card.stories.tsx +0 -151
  278. package/src/components/card/card.tsx +0 -306
  279. package/src/components/carousel/carousel.meta.md +0 -118
  280. package/src/components/carousel/carousel.stories.tsx +0 -89
  281. package/src/components/carousel/carousel.tsx +0 -224
  282. package/src/components/cascader/cascader.meta.md +0 -140
  283. package/src/components/cascader/cascader.stories.tsx +0 -120
  284. package/src/components/cascader/cascader.tsx +0 -548
  285. package/src/components/checkbox/checkbox.meta.md +0 -167
  286. package/src/components/checkbox/checkbox.stories.tsx +0 -288
  287. package/src/components/checkbox/checkbox.tsx +0 -195
  288. package/src/components/collapsible/collapsible.meta.md +0 -88
  289. package/src/components/collapsible/collapsible.stories.tsx +0 -43
  290. package/src/components/collapsible/collapsible.tsx +0 -105
  291. package/src/components/color-picker/color-picker.meta.md +0 -89
  292. package/src/components/color-picker/color-picker.stories.tsx +0 -159
  293. package/src/components/color-picker/color-picker.tsx +0 -171
  294. package/src/components/command/command.meta.md +0 -120
  295. package/src/components/command/command.stories.tsx +0 -59
  296. package/src/components/command/command.tsx +0 -158
  297. package/src/components/context-menu/context-menu.meta.md +0 -93
  298. package/src/components/context-menu/context-menu.stories.tsx +0 -54
  299. package/src/components/context-menu/context-menu.tsx +0 -204
  300. package/src/components/data-table/data-table.meta.md +0 -150
  301. package/src/components/data-table/data-table.stories.tsx +0 -132
  302. package/src/components/data-table/data-table.tsx +0 -185
  303. package/src/components/date-picker/date-picker.meta.md +0 -175
  304. package/src/components/date-picker/date-picker.stories.tsx +0 -108
  305. package/src/components/date-picker/date-picker.tsx +0 -1554
  306. package/src/components/descriptions/descriptions.meta.md +0 -83
  307. package/src/components/descriptions/descriptions.stories.tsx +0 -60
  308. package/src/components/descriptions/descriptions.tsx +0 -137
  309. package/src/components/dialog/dialog.meta.md +0 -168
  310. package/src/components/dialog/dialog.stories.tsx +0 -255
  311. package/src/components/dialog/dialog.tsx +0 -180
  312. package/src/components/dialog/imperative.tsx +0 -252
  313. package/src/components/drawer/drawer.meta.md +0 -95
  314. package/src/components/drawer/drawer.stories.tsx +0 -71
  315. package/src/components/drawer/drawer.tsx +0 -23
  316. package/src/components/dropdown-menu/dropdown-menu.meta.md +0 -171
  317. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +0 -198
  318. package/src/components/dropdown-menu/dropdown-menu.tsx +0 -209
  319. package/src/components/ellipsis/ellipsis.meta.md +0 -87
  320. package/src/components/ellipsis/ellipsis.stories.tsx +0 -72
  321. package/src/components/ellipsis/ellipsis.tsx +0 -153
  322. package/src/components/empty/empty.meta.md +0 -86
  323. package/src/components/empty/empty.stories.tsx +0 -46
  324. package/src/components/empty/empty.tsx +0 -54
  325. package/src/components/field/field.meta.md +0 -154
  326. package/src/components/field/field.stories.tsx +0 -497
  327. package/src/components/field/field.tsx +0 -392
  328. package/src/components/filter-bar/filter-bar.meta.md +0 -92
  329. package/src/components/filter-bar/filter-bar.stories.tsx +0 -1086
  330. package/src/components/filter-bar/filter-bar.tsx +0 -568
  331. package/src/components/flex/flex.meta.md +0 -142
  332. package/src/components/flex/flex.stories.tsx +0 -199
  333. package/src/components/flex/flex.tsx +0 -145
  334. package/src/components/float-button/float-button.meta.md +0 -92
  335. package/src/components/float-button/float-button.stories.tsx +0 -80
  336. package/src/components/float-button/float-button.tsx +0 -143
  337. package/src/components/form/form.meta.md +0 -153
  338. package/src/components/form/form.stories.tsx +0 -472
  339. package/src/components/form/form.tsx +0 -260
  340. package/src/components/grid/grid.meta.md +0 -92
  341. package/src/components/grid/grid.stories.tsx +0 -101
  342. package/src/components/grid/grid.tsx +0 -130
  343. package/src/components/hover-card/hover-card.meta.md +0 -103
  344. package/src/components/hover-card/hover-card.stories.tsx +0 -97
  345. package/src/components/hover-card/hover-card.tsx +0 -67
  346. package/src/components/icon/DEVELOPMENT.md +0 -809
  347. package/src/components/icon/icon.meta.md +0 -170
  348. package/src/components/icon/icon.stories.tsx +0 -344
  349. package/src/components/icon/icon.tsx +0 -248
  350. package/src/components/image/image.meta.md +0 -99
  351. package/src/components/image/image.stories.tsx +0 -55
  352. package/src/components/image/image.tsx +0 -140
  353. package/src/components/input/input.meta.md +0 -115
  354. package/src/components/input/input.stories.tsx +0 -144
  355. package/src/components/input/input.tsx +0 -212
  356. package/src/components/input-group/input-group.meta.md +0 -124
  357. package/src/components/input-group/input-group.stories.tsx +0 -121
  358. package/src/components/input-group/input-group.tsx +0 -143
  359. package/src/components/input-number/input-number.meta.md +0 -148
  360. package/src/components/input-number/input-number.stories.tsx +0 -125
  361. package/src/components/input-number/input-number.tsx +0 -283
  362. package/src/components/input-otp/input-otp.meta.md +0 -106
  363. package/src/components/input-otp/input-otp.stories.tsx +0 -65
  364. package/src/components/input-otp/input-otp.tsx +0 -97
  365. package/src/components/item/item.meta.md +0 -121
  366. package/src/components/item/item.stories.tsx +0 -116
  367. package/src/components/item/item.tsx +0 -172
  368. package/src/components/kbd/kbd.meta.md +0 -94
  369. package/src/components/kbd/kbd.stories.tsx +0 -70
  370. package/src/components/kbd/kbd.tsx +0 -86
  371. package/src/components/label/label.meta.md +0 -99
  372. package/src/components/label/label.stories.tsx +0 -145
  373. package/src/components/label/label.tsx +0 -138
  374. package/src/components/masonry/masonry.meta.md +0 -90
  375. package/src/components/masonry/masonry.stories.tsx +0 -68
  376. package/src/components/masonry/masonry.tsx +0 -60
  377. package/src/components/mentions/mentions.meta.md +0 -119
  378. package/src/components/mentions/mentions.stories.tsx +0 -189
  379. package/src/components/mentions/mentions.tsx +0 -243
  380. package/src/components/menubar/menubar.meta.md +0 -118
  381. package/src/components/menubar/menubar.stories.tsx +0 -141
  382. package/src/components/menubar/menubar.tsx +0 -232
  383. package/src/components/native-select/native-select.meta.md +0 -93
  384. package/src/components/native-select/native-select.stories.tsx +0 -83
  385. package/src/components/native-select/native-select.tsx +0 -54
  386. package/src/components/navigation-menu/navigation-menu.meta.md +0 -118
  387. package/src/components/navigation-menu/navigation-menu.stories.tsx +0 -215
  388. package/src/components/navigation-menu/navigation-menu.tsx +0 -129
  389. package/src/components/notification/notification.meta.md +0 -133
  390. package/src/components/notification/notification.stories.tsx +0 -98
  391. package/src/components/notification/notification.tsx +0 -99
  392. package/src/components/page-header/DEVELOPMENT.md +0 -842
  393. package/src/components/page-header/page-header.meta.md +0 -210
  394. package/src/components/page-header/page-header.stories.tsx +0 -428
  395. package/src/components/page-header/page-header.tsx +0 -284
  396. package/src/components/page-shell/page-shell.meta.md +0 -116
  397. package/src/components/page-shell/page-shell.stories.tsx +0 -149
  398. package/src/components/page-shell/page-shell.tsx +0 -115
  399. package/src/components/pagination/pagination.meta.md +0 -230
  400. package/src/components/pagination/pagination.stories.tsx +0 -284
  401. package/src/components/pagination/pagination.tsx +0 -567
  402. package/src/components/popconfirm/popconfirm.meta.md +0 -114
  403. package/src/components/popconfirm/popconfirm.stories.tsx +0 -75
  404. package/src/components/popconfirm/popconfirm.tsx +0 -134
  405. package/src/components/popover/popover.meta.md +0 -154
  406. package/src/components/popover/popover.stories.tsx +0 -158
  407. package/src/components/popover/popover.tsx +0 -104
  408. package/src/components/progress/progress.meta.md +0 -118
  409. package/src/components/progress/progress.stories.tsx +0 -75
  410. package/src/components/progress/progress.tsx +0 -203
  411. package/src/components/radio-group/radio-group.meta.md +0 -175
  412. package/src/components/radio-group/radio-group.stories.tsx +0 -113
  413. package/src/components/radio-group/radio-group.tsx +0 -209
  414. package/src/components/rate/rate.meta.md +0 -118
  415. package/src/components/rate/rate.stories.tsx +0 -89
  416. package/src/components/rate/rate.tsx +0 -180
  417. package/src/components/resizable/resizable.meta.md +0 -95
  418. package/src/components/resizable/resizable.stories.tsx +0 -104
  419. package/src/components/resizable/resizable.tsx +0 -56
  420. package/src/components/result/result.meta.md +0 -95
  421. package/src/components/result/result.stories.tsx +0 -67
  422. package/src/components/result/result.tsx +0 -100
  423. package/src/components/scroll-area/scroll-area.meta.md +0 -85
  424. package/src/components/scroll-area/scroll-area.stories.tsx +0 -49
  425. package/src/components/scroll-area/scroll-area.tsx +0 -51
  426. package/src/components/segmented/segmented.meta.md +0 -106
  427. package/src/components/segmented/segmented.stories.tsx +0 -130
  428. package/src/components/segmented/segmented.tsx +0 -146
  429. package/src/components/select/select.meta.md +0 -255
  430. package/src/components/select/select.stories.tsx +0 -275
  431. package/src/components/select/select.tsx +0 -735
  432. package/src/components/separator/separator.meta.md +0 -75
  433. package/src/components/separator/separator.stories.tsx +0 -71
  434. package/src/components/separator/separator.tsx +0 -100
  435. package/src/components/sheet/sheet.meta.md +0 -113
  436. package/src/components/sheet/sheet.stories.tsx +0 -188
  437. package/src/components/sheet/sheet.tsx +0 -226
  438. package/src/components/sidebar/sidebar.meta.md +0 -151
  439. package/src/components/sidebar/sidebar.tsx +0 -853
  440. package/src/components/skeleton/skeleton.meta.md +0 -94
  441. package/src/components/skeleton/skeleton.stories.tsx +0 -79
  442. package/src/components/skeleton/skeleton.tsx +0 -144
  443. package/src/components/slider/slider.meta.md +0 -146
  444. package/src/components/slider/slider.stories.tsx +0 -121
  445. package/src/components/slider/slider.tsx +0 -227
  446. package/src/components/sonner/sonner.meta.md +0 -147
  447. package/src/components/sonner/sonner.stories.tsx +0 -164
  448. package/src/components/sonner/sonner.tsx +0 -169
  449. package/src/components/spinner/spinner.meta.md +0 -125
  450. package/src/components/spinner/spinner.stories.tsx +0 -123
  451. package/src/components/spinner/spinner.tsx +0 -166
  452. package/src/components/statistic/statistic.meta.md +0 -104
  453. package/src/components/statistic/statistic.stories.tsx +0 -67
  454. package/src/components/steps/steps.meta.md +0 -116
  455. package/src/components/steps/steps.stories.tsx +0 -115
  456. package/src/components/steps/steps.tsx +0 -173
  457. package/src/components/switch/switch.meta.md +0 -138
  458. package/src/components/switch/switch.stories.tsx +0 -75
  459. package/src/components/switch/switch.tsx +0 -169
  460. package/src/components/table/table.meta.md +0 -106
  461. package/src/components/table/table.stories.tsx +0 -80
  462. package/src/components/table/table.tsx +0 -124
  463. package/src/components/tabs/tabs.meta.md +0 -111
  464. package/src/components/tabs/tabs.stories.tsx +0 -156
  465. package/src/components/tabs/tabs.tsx +0 -190
  466. package/src/components/tag/tag.meta.md +0 -159
  467. package/src/components/tag/tag.stories.tsx +0 -250
  468. package/src/components/tag/tag.tsx +0 -386
  469. package/src/components/textarea/textarea.meta.md +0 -99
  470. package/src/components/textarea/textarea.stories.tsx +0 -89
  471. package/src/components/textarea/textarea.tsx +0 -137
  472. package/src/components/time-picker/time-picker.meta.md +0 -175
  473. package/src/components/time-picker/time-picker.stories.tsx +0 -129
  474. package/src/components/time-picker/time-picker.tsx +0 -946
  475. package/src/components/timeline/timeline.meta.md +0 -110
  476. package/src/components/timeline/timeline.stories.tsx +0 -134
  477. package/src/components/timeline/timeline.tsx +0 -168
  478. package/src/components/toggle/toggle.meta.md +0 -89
  479. package/src/components/toggle/toggle.stories.tsx +0 -66
  480. package/src/components/toggle/toggle.tsx +0 -54
  481. package/src/components/toggle-group/toggle-group.meta.md +0 -91
  482. package/src/components/toggle-group/toggle-group.stories.tsx +0 -83
  483. package/src/components/toggle-group/toggle-group.tsx +0 -78
  484. package/src/components/tooltip/tooltip.meta.md +0 -149
  485. package/src/components/tooltip/tooltip.stories.tsx +0 -108
  486. package/src/components/tooltip/tooltip.tsx +0 -153
  487. package/src/components/tour/tour.meta.md +0 -121
  488. package/src/components/tour/tour.stories.tsx +0 -66
  489. package/src/components/tour/tour.tsx +0 -242
  490. package/src/components/transfer/transfer.meta.md +0 -95
  491. package/src/components/transfer/transfer.stories.tsx +0 -64
  492. package/src/components/transfer/transfer.tsx +0 -258
  493. package/src/components/tree/tree.meta.md +0 -169
  494. package/src/components/tree/tree.stories.tsx +0 -128
  495. package/src/components/tree/tree.tsx +0 -368
  496. package/src/components/tree-select/tree-select.meta.md +0 -151
  497. package/src/components/tree-select/tree-select.stories.tsx +0 -80
  498. package/src/components/tree-select/tree-select.tsx +0 -206
  499. package/src/components/typography/typography.meta.md +0 -149
  500. package/src/components/typography/typography.stories.tsx +0 -116
  501. package/src/components/typography/typography.tsx +0 -260
  502. package/src/components/upload/upload.meta.md +0 -156
  503. package/src/components/upload/upload.stories.tsx +0 -135
  504. package/src/components/upload/upload.tsx +0 -398
  505. package/src/components/watermark/watermark.meta.md +0 -100
  506. package/src/components/watermark/watermark.stories.tsx +0 -170
  507. package/src/components/watermark/watermark.tsx +0 -166
  508. package/src/hooks/use-breakpoint.ts +0 -117
  509. package/src/hooks/use-debounce-callback.ts +0 -52
  510. package/src/stories/theme-tokens.stories.tsx +0 -747
  511. package/src/utils/trigger-input.ts +0 -57
@@ -0,0 +1,639 @@
1
+ /**
2
+ * 穿梭框 Transfer
3
+ *
4
+ * 双栏勾选 + 移动的批量分配交互,将元素在两侧之间穿梭。
5
+ *
6
+ * @when
7
+ * - 权限分配(角色 → 用户)等需要明确「已选 / 未选」分区的批量操作
8
+ * - 字段映射 / 列选择 / 收件人挑选等中量级(10–500 条)多选场景
9
+ * - 需要在面板内完成搜索过滤、自定义渲染或自定义列表(树 / 表格)时
10
+ *
11
+ * @composition
12
+ * Transfer > TransferPanel × 2 + Operations
13
+ */
14
+ import * as React from 'react';
15
+ import { ChevronLeft, ChevronRight, X } from 'lucide-react';
16
+ import { cva } from 'class-variance-authority';
17
+
18
+ import { cn } from '@/lib/utils';
19
+ import { Button } from '@/components/button';
20
+ import { Checkbox } from '@/components/checkbox';
21
+ import { Input } from '@/components/input';
22
+
23
+ // ─── Types ──────────────────────────────────────────────────────────────────
24
+
25
+ interface TransferItem {
26
+ /** 唯一标识。 */
27
+ key: string;
28
+ /** 主标题(列表项主显示文本)。 */
29
+ title: React.ReactNode;
30
+ /** 描述文本(次行小字,可选)。 */
31
+ description?: React.ReactNode;
32
+ /** 单项禁用。 */
33
+ disabled?: boolean;
34
+ }
35
+
36
+ type TransferDirection = 'left' | 'right';
37
+ type TransferSize = 'sm' | 'default' | 'lg';
38
+
39
+ type TransferListBodyProps = {
40
+ /** 当前面板方位。 */
41
+ direction: TransferDirection;
42
+ /** 经搜索过滤后的可见项列表。 */
43
+ filteredItems: TransferItem[];
44
+ /** 当前面板已勾选的 key 列表。 */
45
+ selectedKeys: string[];
46
+ /** 当前面板是否禁用。 */
47
+ disabled: boolean;
48
+ /** 单项勾选切换。 */
49
+ onItemSelect: (key: string, selected: boolean) => void;
50
+ /** 批量勾选切换(用于全选 / 反选)。 */
51
+ onItemSelectAll: (keys: string[], selected: boolean) => void;
52
+ };
53
+
54
+ type TransferLocale = {
55
+ /** 单数计数单位。 @default '项' */
56
+ itemUnit?: string;
57
+ /** 复数计数单位。 @default '项' */
58
+ itemsUnit?: string;
59
+ /** 列表为空时的占位内容。 @default '暂无数据' */
60
+ notFoundContent?: React.ReactNode;
61
+ /** 搜索框 placeholder。 @default '搜索' */
62
+ searchPlaceholder?: string;
63
+ };
64
+
65
+ interface TransferProps
66
+ extends Omit<React.ComponentProps<'div'>, 'onChange' | 'children'> {
67
+ /** 数据源。 */
68
+ dataSource: TransferItem[];
69
+ /** 受控右侧已选 key(穿梭到右侧的项)。 */
70
+ targetKeys?: string[];
71
+ /** 默认右侧已选 key(非受控)。 */
72
+ defaultTargetKeys?: string[];
73
+ /** 受控两侧勾选态 key(包含左右两侧的勾选项)。 */
74
+ selectedKeys?: string[];
75
+ /** 默认两侧勾选态 key(非受控)。 */
76
+ defaultSelectedKeys?: string[];
77
+
78
+ /** 移动回调;direction 为新增项流向的方向。 */
79
+ onChange?: (
80
+ targetKeys: string[],
81
+ direction: TransferDirection,
82
+ moveKeys: string[],
83
+ ) => void;
84
+ /** 勾选态变化回调。 */
85
+ onSelectChange?: (
86
+ sourceSelectedKeys: string[],
87
+ targetSelectedKeys: string[],
88
+ ) => void;
89
+ /** 搜索输入回调。 */
90
+ onSearch?: (direction: TransferDirection, value: string) => void;
91
+
92
+ /** 尺寸。 @default 'default' */
93
+ size?: TransferSize;
94
+ /** 移动模式:normal=勾选 + 按钮;simple=单击即移动。 @default 'normal' */
95
+ mode?: 'normal' | 'simple';
96
+ /** 单向模式(隐藏左移按钮,右侧每行末尾出现移除按钮)。 @default false */
97
+ oneWay?: boolean;
98
+
99
+ /** 是否显示搜索框;boolean 或 [左, 右]。 @default false */
100
+ showSearch?: boolean | [boolean, boolean];
101
+ /** 自定义过滤函数。 */
102
+ filterOption?: (
103
+ input: string,
104
+ item: TransferItem,
105
+ direction: TransferDirection,
106
+ ) => boolean;
107
+ /** 是否显示头部全选 checkbox。 @default true */
108
+ showSelectAll?: boolean;
109
+
110
+ /** 整体禁用。 @default false */
111
+ disabled?: boolean;
112
+ /** 仅禁用左侧面板。 @default false */
113
+ leftDisabled?: boolean;
114
+ /** 仅禁用右侧面板。 @default false */
115
+ rightDisabled?: boolean;
116
+
117
+ /** 左右标题。 @default ['', ''] */
118
+ titles?: [React.ReactNode, React.ReactNode];
119
+ /** 自定义按钮内容;[向右图标, 向左图标]。 */
120
+ operations?: [React.ReactNode, React.ReactNode];
121
+ /** 单项自定义渲染。 */
122
+ render?: (item: TransferItem) => React.ReactNode;
123
+
124
+ /** 列表面板自定义类名(同时作用于左右)。 */
125
+ listClassName?: string;
126
+ /** 列表面板自定义内联样式。 */
127
+ listStyle?: React.CSSProperties;
128
+
129
+ /** 文案本地化。 */
130
+ locale?: TransferLocale;
131
+
132
+ /** 自定义面板 render-prop(antd v5 契约)。传入时由调用方接管列表区。 */
133
+ children?: (panelProps: TransferListBodyProps) => React.ReactNode;
134
+ }
135
+
136
+ // ─── Size cva ───────────────────────────────────────────────────────────────
137
+
138
+ const panelVariants = cva(
139
+ 'flex flex-col rounded-md border border-border bg-card',
140
+ {
141
+ variants: {
142
+ size: {
143
+ sm: 'w-40',
144
+ default: 'w-48',
145
+ lg: 'w-56',
146
+ },
147
+ },
148
+ defaultVariants: { size: 'default' },
149
+ },
150
+ );
151
+
152
+ const listVariants = cva('flex-1 overflow-y-auto p-1', {
153
+ variants: {
154
+ size: {
155
+ sm: 'max-h-40',
156
+ default: 'max-h-50',
157
+ lg: 'max-h-60',
158
+ },
159
+ },
160
+ defaultVariants: { size: 'default' },
161
+ });
162
+
163
+ // 与 Button 的 icon-sm/icon/icon-lg 对齐
164
+ const operationButtonSize = {
165
+ sm: 'icon-sm',
166
+ default: 'icon-sm',
167
+ lg: 'icon',
168
+ } as const;
169
+
170
+ const itemTextSize: Record<TransferSize, string> = {
171
+ sm: 'text-xs',
172
+ default: 'text-xs',
173
+ lg: 'text-sm',
174
+ };
175
+
176
+ // ─── Default filter ─────────────────────────────────────────────────────────
177
+
178
+ function defaultFilter(input: string, item: TransferItem): boolean {
179
+ if (!input) return true;
180
+ if (typeof item.title !== 'string') return true;
181
+ return item.title.toLowerCase().includes(input.toLowerCase());
182
+ }
183
+
184
+ // ─── TransferPanel ──────────────────────────────────────────────────────────
185
+
186
+ interface PanelInternalProps {
187
+ direction: TransferDirection;
188
+ size: TransferSize;
189
+ mode: 'normal' | 'simple';
190
+ items: TransferItem[];
191
+ selectedKeys: string[];
192
+ onSelectChange: (keys: string[]) => void;
193
+ onSimpleMove?: (key: string) => void;
194
+ onItemRemove?: (key: string) => void;
195
+ oneWay: boolean;
196
+ showSearch: boolean;
197
+ showSelectAll: boolean;
198
+ disabled: boolean;
199
+ title: React.ReactNode;
200
+ filterOption?: TransferProps['filterOption'];
201
+ render?: TransferProps['render'];
202
+ locale: Required<TransferLocale>;
203
+ listClassName?: string;
204
+ listStyle?: React.CSSProperties;
205
+ onSearch?: (direction: TransferDirection, value: string) => void;
206
+ children?: TransferProps['children'];
207
+ }
208
+
209
+ function TransferPanel({
210
+ direction,
211
+ size,
212
+ mode,
213
+ items,
214
+ selectedKeys,
215
+ onSelectChange,
216
+ onSimpleMove,
217
+ onItemRemove,
218
+ oneWay,
219
+ showSearch,
220
+ showSelectAll,
221
+ disabled,
222
+ title,
223
+ filterOption,
224
+ render,
225
+ locale,
226
+ listClassName,
227
+ listStyle,
228
+ onSearch,
229
+ children,
230
+ }: PanelInternalProps) {
231
+ const [search, setSearch] = React.useState('');
232
+
233
+ const filtered = React.useMemo(() => {
234
+ if (!search) return items;
235
+ const filterFn = filterOption
236
+ ? (item: TransferItem) => filterOption(search, item, direction)
237
+ : (item: TransferItem) => defaultFilter(search, item);
238
+ return items.filter(filterFn);
239
+ }, [search, items, filterOption, direction]);
240
+
241
+ const selectableKeys = filtered
242
+ .filter((item) => !item.disabled)
243
+ .map((item) => item.key);
244
+ const selectedSet = React.useMemo(
245
+ () => new Set(selectedKeys),
246
+ [selectedKeys],
247
+ );
248
+ const checkedCount = selectableKeys.filter((k) => selectedSet.has(k)).length;
249
+ const allChecked =
250
+ selectableKeys.length > 0 && checkedCount === selectableKeys.length;
251
+ const indeterminate = checkedCount > 0 && !allChecked;
252
+
253
+ const handleSelectAll = (next: boolean | 'indeterminate') => {
254
+ if (next === true) {
255
+ const merged = Array.from(new Set([...selectedKeys, ...selectableKeys]));
256
+ onSelectChange(merged);
257
+ } else {
258
+ const removeSet = new Set(selectableKeys);
259
+ onSelectChange(selectedKeys.filter((k) => !removeSet.has(k)));
260
+ }
261
+ };
262
+
263
+ const onItemSelect = (key: string, next: boolean) => {
264
+ if (next) {
265
+ if (selectedSet.has(key)) return;
266
+ onSelectChange([...selectedKeys, key]);
267
+ } else {
268
+ onSelectChange(selectedKeys.filter((k) => k !== key));
269
+ }
270
+ };
271
+
272
+ const onItemSelectAll = (keys: string[], next: boolean) => {
273
+ if (next) {
274
+ onSelectChange(Array.from(new Set([...selectedKeys, ...keys])));
275
+ } else {
276
+ const removeSet = new Set(keys);
277
+ onSelectChange(selectedKeys.filter((k) => !removeSet.has(k)));
278
+ }
279
+ };
280
+
281
+ const renderItemContent = (item: TransferItem) => {
282
+ if (render) return render(item);
283
+ if (item.description) {
284
+ return (
285
+ <div className="flex min-w-0 flex-col">
286
+ <span className="truncate">{item.title}</span>
287
+ <span className="truncate text-xs text-muted-foreground">
288
+ {item.description}
289
+ </span>
290
+ </div>
291
+ );
292
+ }
293
+ return <span className="truncate">{item.title}</span>;
294
+ };
295
+
296
+ const showHeaderCheckbox = mode === 'normal' && showSelectAll;
297
+ const totalCount = items.length;
298
+
299
+ return (
300
+ <div
301
+ data-slot="transfer-panel"
302
+ data-direction={direction}
303
+ data-size={size}
304
+ className={cn(panelVariants({ size }))}
305
+ >
306
+ {/* Header */}
307
+ <div className="flex items-center gap-2 border-b border-border px-2 py-2">
308
+ {showHeaderCheckbox ? (
309
+ <Checkbox
310
+ checked={
311
+ indeterminate ? 'indeterminate' : allChecked && totalCount > 0
312
+ }
313
+ disabled={disabled || selectableKeys.length === 0}
314
+ onCheckedChange={handleSelectAll}
315
+ />
316
+ ) : null}
317
+ <span className="flex-1 truncate text-xs font-medium">{title}</span>
318
+ <span className="text-xs text-muted-foreground">
319
+ {checkedCount > 0
320
+ ? `${checkedCount}/${totalCount} ${
321
+ totalCount > 1 ? locale.itemsUnit : locale.itemUnit
322
+ }`
323
+ : `${totalCount} ${
324
+ totalCount > 1 ? locale.itemsUnit : locale.itemUnit
325
+ }`}
326
+ </span>
327
+ </div>
328
+
329
+ {/* Search */}
330
+ {showSearch ? (
331
+ <div
332
+ data-slot="transfer-search"
333
+ className="px-2 pt-1.5 pb-2"
334
+ >
335
+ <Input
336
+ value={search}
337
+ disabled={disabled}
338
+ placeholder={locale.searchPlaceholder}
339
+ onChange={(e) => {
340
+ setSearch(e.target.value);
341
+ onSearch?.(direction, e.target.value);
342
+ }}
343
+ />
344
+ </div>
345
+ ) : null}
346
+
347
+ {/* List */}
348
+ <div
349
+ data-slot="transfer-list"
350
+ className={cn(listVariants({ size }), listClassName)}
351
+ style={listStyle}
352
+ >
353
+ {typeof children === 'function' ? (
354
+ children({
355
+ direction,
356
+ filteredItems: filtered,
357
+ selectedKeys,
358
+ disabled,
359
+ onItemSelect,
360
+ onItemSelectAll,
361
+ })
362
+ ) : filtered.length === 0 ? (
363
+ <div className="py-6 text-center text-xs text-muted-foreground">
364
+ {locale.notFoundContent}
365
+ </div>
366
+ ) : (
367
+ filtered.map((item) => {
368
+ const itemDisabled = disabled || !!item.disabled;
369
+ const checked = selectedSet.has(item.key);
370
+ const showRemove = direction === 'right' && oneWay && !itemDisabled;
371
+
372
+ return (
373
+ <div
374
+ key={item.key}
375
+ data-slot="transfer-list-item"
376
+ data-disabled={itemDisabled || undefined}
377
+ data-checked={checked || undefined}
378
+ className={cn(
379
+ 'group/transfer-item flex items-center gap-2 rounded-sm px-1.5 py-2 transition-colors',
380
+ itemTextSize[size],
381
+ itemDisabled
382
+ ? 'pointer-events-none opacity-50'
383
+ : 'cursor-pointer hover:bg-accent/50',
384
+ checked && mode === 'normal' && 'bg-accent/30',
385
+ )}
386
+ onClick={() => {
387
+ if (itemDisabled) return;
388
+ if (mode === 'simple') {
389
+ onSimpleMove?.(item.key);
390
+ return;
391
+ }
392
+ onItemSelect(item.key, !checked);
393
+ }}
394
+ >
395
+ {mode === 'normal' ? (
396
+ <Checkbox
397
+ checked={checked}
398
+ disabled={itemDisabled}
399
+ onCheckedChange={(next) =>
400
+ onItemSelect(item.key, next === true)
401
+ }
402
+ onClick={(e) => e.stopPropagation()}
403
+ />
404
+ ) : null}
405
+ <div className="min-w-0 flex-1">{renderItemContent(item)}</div>
406
+ {showRemove ? (
407
+ <Button
408
+ size="icon-sm"
409
+ variant="ghost"
410
+ className="opacity-0 group-hover/transfer-item:opacity-100"
411
+ onClick={(e) => {
412
+ e.stopPropagation();
413
+ onItemRemove?.(item.key);
414
+ }}
415
+ >
416
+ <X />
417
+ </Button>
418
+ ) : null}
419
+ </div>
420
+ );
421
+ })
422
+ )}
423
+ </div>
424
+ </div>
425
+ );
426
+ }
427
+
428
+ // ─── Transfer ───────────────────────────────────────────────────────────────
429
+
430
+ const DEFAULT_LOCALE: Required<TransferLocale> = {
431
+ itemUnit: '项',
432
+ itemsUnit: '项',
433
+ notFoundContent: '暂无数据',
434
+ searchPlaceholder: '搜索',
435
+ };
436
+
437
+ function Transfer({
438
+ dataSource,
439
+ targetKeys: controlledTargetKeys,
440
+ defaultTargetKeys,
441
+ selectedKeys: controlledSelectedKeys,
442
+ defaultSelectedKeys,
443
+ onChange,
444
+ onSelectChange,
445
+ onSearch,
446
+ size = 'default',
447
+ mode = 'normal',
448
+ oneWay = false,
449
+ showSearch = false,
450
+ filterOption,
451
+ showSelectAll = true,
452
+ disabled = false,
453
+ leftDisabled = false,
454
+ rightDisabled = false,
455
+ titles,
456
+ operations,
457
+ render,
458
+ listClassName,
459
+ listStyle,
460
+ locale: localeProp,
461
+ children,
462
+ className,
463
+ ...props
464
+ }: TransferProps) {
465
+ // 受控合并
466
+ const [internalTargetKeys, setInternalTargetKeys] = React.useState<string[]>(
467
+ defaultTargetKeys ?? [],
468
+ );
469
+ const targetKeys = controlledTargetKeys ?? internalTargetKeys;
470
+
471
+ const [internalSelectedKeys, setInternalSelectedKeys] = React.useState<
472
+ string[]
473
+ >(defaultSelectedKeys ?? []);
474
+ const selectedKeys = controlledSelectedKeys ?? internalSelectedKeys;
475
+
476
+ const locale = { ...DEFAULT_LOCALE, ...localeProp };
477
+
478
+ const targetSet = React.useMemo(() => new Set(targetKeys), [targetKeys]);
479
+ const leftItems = React.useMemo(
480
+ () => dataSource.filter((item) => !targetSet.has(item.key)),
481
+ [dataSource, targetSet],
482
+ );
483
+ const rightItems = React.useMemo(
484
+ () => dataSource.filter((item) => targetSet.has(item.key)),
485
+ [dataSource, targetSet],
486
+ );
487
+
488
+ const leftSelectedKeys = React.useMemo(() => {
489
+ const leftKeySet = new Set(leftItems.map((i) => i.key));
490
+ return selectedKeys.filter((k) => leftKeySet.has(k));
491
+ }, [leftItems, selectedKeys]);
492
+
493
+ const rightSelectedKeys = React.useMemo(() => {
494
+ const rightKeySet = new Set(rightItems.map((i) => i.key));
495
+ return selectedKeys.filter((k) => rightKeySet.has(k));
496
+ }, [rightItems, selectedKeys]);
497
+
498
+ const updateSelectedKeys = (next: string[]) => {
499
+ if (controlledSelectedKeys === undefined) setInternalSelectedKeys(next);
500
+ const leftKeySet = new Set(leftItems.map((i) => i.key));
501
+ const rightKeySet = new Set(rightItems.map((i) => i.key));
502
+ onSelectChange?.(
503
+ next.filter((k) => leftKeySet.has(k)),
504
+ next.filter((k) => rightKeySet.has(k)),
505
+ );
506
+ };
507
+
508
+ const handlePanelSelectChange = (
509
+ direction: TransferDirection,
510
+ nextKeys: string[],
511
+ ) => {
512
+ const otherKeys =
513
+ direction === 'left' ? rightSelectedKeys : leftSelectedKeys;
514
+ updateSelectedKeys([...otherKeys, ...nextKeys]);
515
+ };
516
+
517
+ const moveItems = (moveKeys: string[], direction: TransferDirection) => {
518
+ if (moveKeys.length === 0) return;
519
+ const moveSet = new Set(moveKeys);
520
+ const newTargetKeys =
521
+ direction === 'right'
522
+ ? [...targetKeys, ...moveKeys]
523
+ : targetKeys.filter((k) => !moveSet.has(k));
524
+ if (controlledTargetKeys === undefined)
525
+ setInternalTargetKeys(newTargetKeys);
526
+ onChange?.(newTargetKeys, direction, moveKeys);
527
+ // 清掉已经移出去的勾选
528
+ updateSelectedKeys(selectedKeys.filter((k) => !moveSet.has(k)));
529
+ };
530
+
531
+ const moveToRight = () => moveItems(leftSelectedKeys, 'right');
532
+ const moveToLeft = () => moveItems(rightSelectedKeys, 'left');
533
+
534
+ const handleSimpleMove = (direction: TransferDirection) => (key: string) => {
535
+ moveItems([key], direction === 'left' ? 'right' : 'left');
536
+ };
537
+
538
+ const showSearchTuple: [boolean, boolean] = Array.isArray(showSearch)
539
+ ? showSearch
540
+ : [showSearch, showSearch];
541
+
542
+ const leftPanelDisabled = disabled || leftDisabled;
543
+ const rightPanelDisabled = disabled || rightDisabled;
544
+
545
+ const [rightOp, leftOp] = operations ?? [<ChevronRight />, <ChevronLeft />];
546
+
547
+ const moveToRightDisabled = disabled || leftSelectedKeys.length === 0;
548
+ const moveToLeftDisabled = disabled || rightSelectedKeys.length === 0;
549
+
550
+ return (
551
+ <div
552
+ data-slot="transfer"
553
+ data-size={size}
554
+ data-mode={mode}
555
+ className={cn('inline-flex items-start gap-2', className)}
556
+ {...props}
557
+ >
558
+ <TransferPanel
559
+ direction="left"
560
+ size={size}
561
+ mode={mode}
562
+ items={leftItems}
563
+ selectedKeys={leftSelectedKeys}
564
+ onSelectChange={(keys) => handlePanelSelectChange('left', keys)}
565
+ onSimpleMove={handleSimpleMove('left')}
566
+ oneWay={oneWay}
567
+ showSearch={showSearchTuple[0]}
568
+ showSelectAll={showSelectAll}
569
+ disabled={leftPanelDisabled}
570
+ title={titles?.[0]}
571
+ filterOption={filterOption}
572
+ render={render}
573
+ locale={locale}
574
+ listClassName={listClassName}
575
+ listStyle={listStyle}
576
+ onSearch={onSearch}
577
+ children={children}
578
+ />
579
+
580
+ {mode === 'normal' ? (
581
+ <div
582
+ data-slot="transfer-operations"
583
+ className="flex flex-col gap-1 self-center"
584
+ >
585
+ <Button
586
+ variant={moveToRightDisabled ? 'outline' : 'default'}
587
+ size={operationButtonSize[size]}
588
+ disabled={moveToRightDisabled}
589
+ onClick={moveToRight}
590
+ >
591
+ {rightOp}
592
+ </Button>
593
+ {!oneWay ? (
594
+ <Button
595
+ variant={moveToLeftDisabled ? 'outline' : 'default'}
596
+ size={operationButtonSize[size]}
597
+ disabled={moveToLeftDisabled}
598
+ onClick={moveToLeft}
599
+ >
600
+ {leftOp}
601
+ </Button>
602
+ ) : null}
603
+ </div>
604
+ ) : null}
605
+
606
+ <TransferPanel
607
+ direction="right"
608
+ size={size}
609
+ mode={mode}
610
+ items={rightItems}
611
+ selectedKeys={rightSelectedKeys}
612
+ onSelectChange={(keys) => handlePanelSelectChange('right', keys)}
613
+ onSimpleMove={handleSimpleMove('right')}
614
+ onItemRemove={(key) => moveItems([key], 'left')}
615
+ oneWay={oneWay}
616
+ showSearch={showSearchTuple[1]}
617
+ showSelectAll={showSelectAll}
618
+ disabled={rightPanelDisabled}
619
+ title={titles?.[1]}
620
+ filterOption={filterOption}
621
+ render={render}
622
+ locale={locale}
623
+ listClassName={listClassName}
624
+ listStyle={listStyle}
625
+ onSearch={onSearch}
626
+ children={children}
627
+ />
628
+ </div>
629
+ );
630
+ }
631
+
632
+ export { Transfer };
633
+ export type {
634
+ TransferProps,
635
+ TransferItem,
636
+ TransferDirection,
637
+ TransferListBodyProps,
638
+ TransferLocale,
639
+ };