@gmfe/react 2.14.20 → 2.14.26-beta.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 (377) hide show
  1. package/LICENSE.md +4 -0
  2. package/package.json +3 -3
  3. package/src/common/hooks/index.js +3 -3
  4. package/src/common/hooks/use_mutation_observer.js +25 -25
  5. package/src/common/util.js +52 -52
  6. package/src/component/affix/affix.stories.js +13 -13
  7. package/src/component/affix/index.js +21 -21
  8. package/src/component/box/box.js +31 -31
  9. package/src/component/box/box.stories.js +94 -94
  10. package/src/component/box/box_form.js +77 -77
  11. package/src/component/box/box_panel.js +91 -91
  12. package/src/component/box/box_table.js +51 -51
  13. package/src/component/box/index.js +6 -6
  14. package/src/component/box/style.less +39 -39
  15. package/src/component/button/button.stories.js +91 -91
  16. package/src/component/button/index.js +92 -92
  17. package/src/component/button/style.less +114 -114
  18. package/src/component/calendar/calendar.js +52 -52
  19. package/src/component/calendar/calendar.stories.js +57 -57
  20. package/src/component/calendar/content.js +89 -89
  21. package/src/component/calendar/day.js +109 -109
  22. package/src/component/calendar/head.js +243 -243
  23. package/src/component/calendar/index.js +4 -4
  24. package/src/component/calendar/range_calendar.js +150 -150
  25. package/src/component/calendar/style.less +140 -140
  26. package/src/component/calendar/week.js +27 -27
  27. package/src/component/carousel/carousel.js +178 -178
  28. package/src/component/carousel/stories.js +50 -50
  29. package/src/component/carousel/style.less +48 -48
  30. package/src/component/cascader/cascader.js +441 -443
  31. package/src/component/cascader/cascader.select.js +195 -195
  32. package/src/component/cascader/stories.js +240 -240
  33. package/src/component/cascader/style.less +122 -122
  34. package/src/component/checkbox/checkbox.js +86 -86
  35. package/src/component/checkbox/checkbox_group.js +66 -66
  36. package/src/component/checkbox/index.js +4 -4
  37. package/src/component/checkbox/stories.js +103 -103
  38. package/src/component/checkbox/style.less +88 -88
  39. package/src/component/collapse/collapse.stories.js +18 -18
  40. package/src/component/collapse/index.js +36 -36
  41. package/src/component/color_picker/index.js +190 -190
  42. package/src/component/color_picker/stories.js +17 -17
  43. package/src/component/color_picker/style.less +41 -41
  44. package/src/component/date_picker/date_picker.stories.js +102 -102
  45. package/src/component/date_picker/index.js +217 -217
  46. package/src/component/date_picker/overlay.js +119 -119
  47. package/src/component/date_picker/style.less +22 -22
  48. package/src/component/date_picker/time_select.js +62 -62
  49. package/src/component/date_range_picker/date_range_picker.stories.js +196 -196
  50. package/src/component/date_range_picker/index.js +206 -206
  51. package/src/component/date_range_picker/left.js +127 -127
  52. package/src/component/date_range_picker/overlay.js +202 -202
  53. package/src/component/date_range_picker/style.less +46 -46
  54. package/src/component/date_range_picker/time_range_select.js +150 -150
  55. package/src/component/date_range_picker/two.js +129 -129
  56. package/src/component/date_range_picker/util.js +42 -42
  57. package/src/component/dialog/index.js +240 -240
  58. package/src/component/dialog/stories.js +125 -125
  59. package/src/component/divider/index.js +28 -28
  60. package/src/component/divider/stories.js +5 -5
  61. package/src/component/divider/style.less +15 -15
  62. package/src/component/drawer/index.js +107 -107
  63. package/src/component/drawer/style.less +43 -43
  64. package/src/component/drop_down/drop_down.js +84 -84
  65. package/src/component/drop_down/drop_down_item.js +43 -43
  66. package/src/component/drop_down/drop_down_items.js +22 -22
  67. package/src/component/drop_down/index.js +5 -5
  68. package/src/component/drop_down/stories.js +38 -38
  69. package/src/component/drop_down/style.less +21 -21
  70. package/src/component/drop_select/index.js +208 -208
  71. package/src/component/drop_select/style.less +69 -69
  72. package/src/component/dropper/index.js +62 -62
  73. package/src/component/dropper/style.less +18 -18
  74. package/src/component/editable_text/editable_text.stories.js +47 -47
  75. package/src/component/editable_text/index.js +106 -106
  76. package/src/component/editable_text/style.less +29 -29
  77. package/src/component/filter_select/filter.select.js +416 -416
  78. package/src/component/filter_select/multiple.filter.select.js +425 -425
  79. package/src/component/filter_select/style.less +117 -117
  80. package/src/component/flex/index.js +132 -132
  81. package/src/component/flex/stories.js +13 -13
  82. package/src/component/flex/style.less +101 -101
  83. package/src/component/flip_number/index.js +196 -196
  84. package/src/component/flip_number/stories.js +25 -25
  85. package/src/component/flip_number/utils.js +50 -50
  86. package/src/component/form/form.js +153 -153
  87. package/src/component/form/form.stories.js +553 -553
  88. package/src/component/form/form_block.js +59 -59
  89. package/src/component/form/form_button.js +29 -29
  90. package/src/component/form/form_group.js +173 -173
  91. package/src/component/form/form_item.js +174 -163
  92. package/src/component/form/form_panel.js +71 -71
  93. package/src/component/form/index.js +8 -8
  94. package/src/component/form/style.less +130 -130
  95. package/src/component/form/util.js +13 -13
  96. package/src/component/function_set/function_set.stories.js +91 -91
  97. package/src/component/function_set/index.js +98 -98
  98. package/src/component/function_set/overlay.js +56 -56
  99. package/src/component/grid/col.js +72 -72
  100. package/src/component/grid/grid.stories.js +123 -123
  101. package/src/component/grid/index.js +4 -4
  102. package/src/component/grid/mixin.less +48 -48
  103. package/src/component/grid/row.js +44 -44
  104. package/src/component/grid/style.less +26 -26
  105. package/src/component/grid/util.js +11 -11
  106. package/src/component/icon_down_up/index.js +28 -28
  107. package/src/component/icon_down_up/stories.js +18 -18
  108. package/src/component/icon_down_up/style.less +8 -8
  109. package/src/component/image_preview/index.js +20 -20
  110. package/src/component/image_preview/preview_modal.js +193 -193
  111. package/src/component/image_preview/style.less +119 -119
  112. package/src/component/img_uploader/index.js +149 -149
  113. package/src/component/img_uploader/index.stories.js +51 -51
  114. package/src/component/img_uploader/style.less +22 -22
  115. package/src/component/input/index.js +19 -19
  116. package/src/component/input_number/index.js +73 -73
  117. package/src/component/input_number/number.js +158 -158
  118. package/src/component/input_number/stories.js +21 -21
  119. package/src/component/input_number/style.less +10 -10
  120. package/src/component/layout_root/index.js +165 -165
  121. package/src/component/lazy_img/index.js +68 -68
  122. package/src/component/level_list/index.js +120 -120
  123. package/src/component/level_list/level_item.js +64 -64
  124. package/src/component/level_list/level_list.stories.js +139 -139
  125. package/src/component/level_list/style.less +47 -47
  126. package/src/component/level_list/util.js +22 -22
  127. package/src/component/level_select/index.js +240 -240
  128. package/src/component/level_select/level_select.stories.js +67 -67
  129. package/src/component/list/base.js +155 -155
  130. package/src/component/list/index.js +93 -93
  131. package/src/component/list/list.stories.js +99 -99
  132. package/src/component/list/style.less +58 -58
  133. package/src/component/loading/index.js +45 -45
  134. package/src/component/loading/loading_chunk.js +59 -59
  135. package/src/component/loading/loading_full_screen.js +62 -62
  136. package/src/component/loading/stories.js +46 -46
  137. package/src/component/loading/style.less +92 -92
  138. package/src/component/mask/index.js +34 -34
  139. package/src/component/mask/style.less +10 -10
  140. package/src/component/modal/clean_modal.js +36 -36
  141. package/src/component/modal/index.js +293 -293
  142. package/src/component/modal/right_side_modal.js +37 -37
  143. package/src/component/modal/stories.js +96 -96
  144. package/src/component/modal/style.less +145 -145
  145. package/src/component/more_select/base.js +517 -517
  146. package/src/component/more_select/index.js +91 -91
  147. package/src/component/more_select/stories.js +261 -261
  148. package/src/component/more_select/style.less +130 -130
  149. package/src/component/nav/index.js +269 -269
  150. package/src/component/nav/nav.stories.js +133 -133
  151. package/src/component/nav/style.less +156 -156
  152. package/src/component/nprogress/index.js +34 -34
  153. package/src/component/nprogress/stories.js +22 -22
  154. package/src/component/nprogress/style.less +39 -39
  155. package/src/component/pagination/base.js +67 -67
  156. package/src/component/pagination/left.js +65 -65
  157. package/src/component/pagination/page.js +120 -120
  158. package/src/component/pagination/page_peek.js +96 -96
  159. package/src/component/pagination/pagination.js +54 -54
  160. package/src/component/pagination/pagination.stories.js +104 -104
  161. package/src/component/pagination/pagination_text.js +71 -71
  162. package/src/component/pagination/pagination_v2.js +30 -30
  163. package/src/component/pagination/right.js +67 -67
  164. package/src/component/pagination/style.less +52 -52
  165. package/src/component/pagination/util.js +5 -5
  166. package/src/component/picture_preview/index.js +21 -21
  167. package/src/component/popover/index.js +373 -373
  168. package/src/component/popover/stories.js +101 -101
  169. package/src/component/popup/index.js +4 -4
  170. package/src/component/popup/popup.js +172 -172
  171. package/src/component/popup/popup_content_confirm.js +67 -67
  172. package/src/component/popup/style.less +105 -105
  173. package/src/component/price/index.js +147 -147
  174. package/src/component/price/stories.js +34 -34
  175. package/src/component/progress/index.js +101 -101
  176. package/src/component/progress/stories.js +60 -60
  177. package/src/component/progress/style.less +88 -88
  178. package/src/component/progress_circle/index.js +116 -116
  179. package/src/component/progress_circle/stories.js +54 -54
  180. package/src/component/progress_circle/style.less +17 -17
  181. package/src/component/radio/index.js +4 -4
  182. package/src/component/radio/radio.js +76 -76
  183. package/src/component/radio/radio_group.js +51 -51
  184. package/src/component/radio/stories.js +80 -80
  185. package/src/component/radio/style.less +63 -63
  186. package/src/component/recommend_input/index.js +118 -118
  187. package/src/component/recommend_input/recommend_input.stories.js +56 -56
  188. package/src/component/recommend_input/style.less +25 -25
  189. package/src/component/select/index.js +4 -4
  190. package/src/component/select/option.js +22 -22
  191. package/src/component/select/select.js +186 -186
  192. package/src/component/select/select.stories.js +79 -79
  193. package/src/component/select/style.less +4 -4
  194. package/src/component/selection/index.js +132 -132
  195. package/src/component/selection/selection.stories.js +41 -41
  196. package/src/component/selection/style.less +67 -67
  197. package/src/component/sheet/index.js +7 -7
  198. package/src/component/sheet/sheet.js +348 -348
  199. package/src/component/sheet/sheet_action.js +16 -16
  200. package/src/component/sheet/sheet_batch_action.js +16 -16
  201. package/src/component/sheet/sheet_column.js +21 -21
  202. package/src/component/sheet/sheet_select.js +31 -31
  203. package/src/component/sheet/stories.js +210 -210
  204. package/src/component/sheet/style.less +95 -95
  205. package/src/component/steps/index.js +66 -66
  206. package/src/component/steps/steps.stories.js +15 -15
  207. package/src/component/steps/style.less +39 -39
  208. package/src/component/storage/index.js +54 -54
  209. package/src/component/storage/stories.js +38 -38
  210. package/src/component/switch/index.js +118 -118
  211. package/src/component/switch/stories.js +7 -7
  212. package/src/component/switch/style.less +70 -70
  213. package/src/component/table_select/index.js +152 -152
  214. package/src/component/table_select/style.less +12 -12
  215. package/src/component/table_select/table_select.stories.js +91 -91
  216. package/src/component/table_select/util.js +21 -21
  217. package/src/component/tabs/style.less +33 -33
  218. package/src/component/tabs/tabs.js +97 -97
  219. package/src/component/tabs/tabs.stories.js +48 -48
  220. package/src/component/time_span/style.less +45 -45
  221. package/src/component/time_span/time_span.js +183 -183
  222. package/src/component/time_span/time_span.stories.js +66 -66
  223. package/src/component/time_span/time_span_picker.js +112 -112
  224. package/src/component/time_span/time_span_picker.stories.js +71 -71
  225. package/src/component/tip/index.js +168 -168
  226. package/src/component/tip/stories.js +54 -54
  227. package/src/component/tip/style.less +41 -41
  228. package/src/component/tool_tip/index.js +58 -58
  229. package/src/component/tool_tip/stories.js +36 -36
  230. package/src/component/transfer/box.js +186 -186
  231. package/src/component/transfer/index.js +4 -4
  232. package/src/component/transfer/stories.js +108 -108
  233. package/src/component/transfer/style.less +34 -34
  234. package/src/component/transfer/transfer.js +181 -181
  235. package/src/component/transfer/transfer_group.js +178 -178
  236. package/src/component/transfer_v2/index.js +171 -171
  237. package/src/component/transfer_v2/transfer_v2.stories.js +226 -226
  238. package/src/component/tree/bottom.js +41 -41
  239. package/src/component/tree/index.js +205 -205
  240. package/src/component/tree/item.js +154 -154
  241. package/src/component/tree/list.js +151 -151
  242. package/src/component/tree/style.less +147 -147
  243. package/src/component/tree/tree.stories.js +241 -241
  244. package/src/component/tree/util.js +24 -24
  245. package/src/component/tree_v2/bottom.js +40 -40
  246. package/src/component/tree_v2/index.js +260 -260
  247. package/src/component/tree_v2/list.js +230 -230
  248. package/src/component/tree_v2/style.less +38 -38
  249. package/src/component/tree_v2/tree.stories.js +419 -419
  250. package/src/component/tree_v2/util.js +185 -185
  251. package/src/component/uploader/index.js +108 -108
  252. package/src/component/uploader/style.less +24 -24
  253. package/src/component/uploader/uploader.stories.js +51 -51
  254. package/src/css/arrow.less +56 -56
  255. package/src/css/bg.less +52 -52
  256. package/src/css/border.less +40 -40
  257. package/src/css/cover.less +236 -236
  258. package/src/css/cursor.less +19 -19
  259. package/src/css/display.less +16 -16
  260. package/src/css/distance.less +324 -324
  261. package/src/css/error.less +10 -10
  262. package/src/css/other.less +16 -16
  263. package/src/css/overflow.less +23 -23
  264. package/src/css/position.less +11 -11
  265. package/src/css/rotate.less +28 -28
  266. package/src/css/shadow.less +11 -11
  267. package/src/css/stories.js +104 -104
  268. package/src/css/svg.less +51 -51
  269. package/src/css/text.less +120 -120
  270. package/src/css/variables.less +62 -62
  271. package/src/event_type.js +16 -16
  272. package/src/fonts/glyphicons-halflings-regular.svg +542 -542
  273. package/src/index.js +237 -237
  274. package/src/index.less +108 -108
  275. package/src/less/.csscomb.json +304 -304
  276. package/src/less/.csslintrc +19 -19
  277. package/src/less/alerts.less +72 -72
  278. package/src/less/badges.less +65 -65
  279. package/src/less/bootstrap.less +51 -51
  280. package/src/less/breadcrumbs.less +25 -25
  281. package/src/less/button-groups.less +253 -253
  282. package/src/less/buttons.less +186 -186
  283. package/src/less/carousel.less +269 -269
  284. package/src/less/close.less +33 -33
  285. package/src/less/code.less +68 -68
  286. package/src/less/component-animations.less +39 -39
  287. package/src/less/custom.less +37 -37
  288. package/src/less/dropdowns.less +215 -215
  289. package/src/less/forms.less +612 -612
  290. package/src/less/glyphicons.less +1614 -1614
  291. package/src/less/grid.less +76 -76
  292. package/src/less/input-groups.less +175 -175
  293. package/src/less/jumbotron.less +53 -53
  294. package/src/less/labels.less +64 -64
  295. package/src/less/list-group.less +126 -126
  296. package/src/less/media.less +66 -66
  297. package/src/less/mixins/alerts.less +14 -14
  298. package/src/less/mixins/background-variant.less +9 -9
  299. package/src/less/mixins/border-radius.less +21 -21
  300. package/src/less/mixins/buttons.less +65 -65
  301. package/src/less/mixins/center-block.less +7 -7
  302. package/src/less/mixins/clearfix.less +22 -22
  303. package/src/less/mixins/forms.less +84 -84
  304. package/src/less/mixins/gradients.less +59 -59
  305. package/src/less/mixins/grid-framework.less +96 -96
  306. package/src/less/mixins/grid.less +134 -134
  307. package/src/less/mixins/hide-text.less +21 -21
  308. package/src/less/mixins/image.less +25 -25
  309. package/src/less/mixins/labels.less +12 -12
  310. package/src/less/mixins/list-group.less +30 -30
  311. package/src/less/mixins/nav-divider.less +10 -10
  312. package/src/less/mixins/nav-vertical-align.less +9 -9
  313. package/src/less/mixins/opacity.less +8 -8
  314. package/src/less/mixins/pagination.less +24 -24
  315. package/src/less/mixins/panels.less +24 -24
  316. package/src/less/mixins/progress-bar.less +10 -10
  317. package/src/less/mixins/reset-filter.less +8 -8
  318. package/src/less/mixins/reset-text.less +18 -18
  319. package/src/less/mixins/resize.less +6 -6
  320. package/src/less/mixins/responsive-visibility.less +21 -21
  321. package/src/less/mixins/size.less +10 -10
  322. package/src/less/mixins/tab-focus.less +9 -9
  323. package/src/less/mixins/table-row.less +28 -28
  324. package/src/less/mixins/text-emphasis.less +9 -9
  325. package/src/less/mixins/text-overflow.less +8 -8
  326. package/src/less/mixins/vendor-prefixes.less +254 -254
  327. package/src/less/mixins.less +36 -36
  328. package/src/less/modals.less +163 -163
  329. package/src/less/navbar.less +651 -651
  330. package/src/less/navs.less +236 -236
  331. package/src/less/normalize.less +424 -424
  332. package/src/less/pager.less +54 -54
  333. package/src/less/pagination.less +90 -90
  334. package/src/less/panels.less +274 -274
  335. package/src/less/popovers.less +140 -140
  336. package/src/less/print.less +103 -103
  337. package/src/less/progress-bars.less +92 -92
  338. package/src/less/responsive-embed.less +35 -35
  339. package/src/less/responsive-utilities.less +209 -209
  340. package/src/less/scaffolding.less +154 -154
  341. package/src/less/tables.less +228 -228
  342. package/src/less/theme.less +344 -344
  343. package/src/less/thumbnails.less +35 -35
  344. package/src/less/tooltip.less +115 -115
  345. package/src/less/type.less +352 -352
  346. package/src/less/utilities.less +57 -57
  347. package/src/less/variables.less +833 -833
  348. package/src/less/wells.less +29 -29
  349. package/src/sotries.js +4 -4
  350. package/src/validator/index.js +10 -10
  351. package/src/validator/rules.js +66 -66
  352. package/src/validator/type.js +10 -10
  353. package/src/validator/validator.js +86 -86
  354. package/src/var.less +4 -4
  355. package/svg/calendar-month.svg +8 -8
  356. package/svg/calendar-year.svg +13 -13
  357. package/svg/calendar.svg +17 -17
  358. package/svg/check-detail.svg +18 -18
  359. package/svg/close-circle.svg +13 -13
  360. package/svg/closeup.svg +20 -20
  361. package/svg/delete.svg +10 -10
  362. package/svg/down-small.svg +1 -1
  363. package/svg/down.svg +1 -1
  364. package/svg/edit-box.svg +17 -17
  365. package/svg/edit-pen.svg +17 -17
  366. package/svg/empty.svg +27 -27
  367. package/svg/expand.svg +21 -21
  368. package/svg/left-small.svg +1 -1
  369. package/svg/more.svg +10 -10
  370. package/svg/next.svg +40 -40
  371. package/svg/pen.svg +12 -12
  372. package/svg/remove.svg +1 -1
  373. package/svg/right-small.svg +1 -1
  374. package/svg/search.svg +8 -8
  375. package/svg/setting.svg +17 -17
  376. package/svg/up-small.svg +1 -1
  377. package/svg/up.svg +1 -1
@@ -1,443 +1,441 @@
1
- import React, { useEffect } from 'react'
2
- import PropTypes from 'prop-types'
3
- import _ from 'lodash'
4
- import classNames from 'classnames'
5
- import Flex from '../flex'
6
- import Popover from '../popover'
7
- import { pinYinFilter, pinyin } from '@gm-common/tool'
8
- import SVGCloseCircle from '../../../svg/close-circle.svg'
9
- import SVGDownSmall from '../../../svg/down.svg'
10
- import SVGUpSmall from '../../../svg/up.svg'
11
-
12
- // 给list中每个元素添加_path
13
- function mapPath(list, searchText, parentPath = []) {
14
- _.each(list, item => {
15
- if (item._path === undefined) {
16
- item._path = [...parentPath, item.value]
17
- }
18
-
19
- if (item.children) {
20
- mapPath(item.children, searchText, [...item._path])
21
- }
22
- })
23
- }
24
-
25
- // 找出list树下匹配searchText的最深元素的路径
26
- function getMaxDeepPathOfMatchElement(list, searchText) {
27
- let maxLengthPath = []
28
-
29
- function findMaxLengthPath(list, searchText) {
30
- _.each(list, item => {
31
- // 匹配首字母
32
- const firstLetter = _.map(
33
- pinyin(item.name, 'first_letter'),
34
- value => value[0]
35
- ).join('')
36
- // 全拼集合
37
- const normal = _.map(pinyin(item.name), value => value[0]).join('')
38
-
39
- if (
40
- (item.name.indexOf(searchText) > -1 ||
41
- normal.indexOf(searchText) > -1 ||
42
- firstLetter.indexOf(searchText) > -1) &&
43
- maxLengthPath.length < item._path.length
44
- ) {
45
- maxLengthPath = item._path
46
- }
47
-
48
- if (item.children) {
49
- findMaxLengthPath(item.children, searchText)
50
- }
51
- })
52
- }
53
-
54
- findMaxLengthPath(list, searchText)
55
-
56
- return maxLengthPath
57
- }
58
-
59
- const Overlay = ({
60
- className,
61
- style,
62
- selected,
63
- list,
64
- handleSelect,
65
- handleMouseEnter,
66
- filterLastResultID
67
- }) => {
68
- useEffect(() => {
69
- _.each(selected, id => {
70
- const $dom = document.getElementById(id)
71
- $dom && $dom.scrollIntoViewIfNeeded()
72
- })
73
- }, [])
74
-
75
- useEffect(() => {
76
- if (filterLastResultID) {
77
- const $dom = document.getElementById(filterLastResultID)
78
- $dom && $dom.scrollIntoViewIfNeeded()
79
- }
80
- }, [filterLastResultID])
81
-
82
- return (
83
- <Flex
84
- className={classNames('gm-cascader-list gm-bg', className)}
85
- style={style}
86
- >
87
- {_.map(list, (value, i) => (
88
- <Flex
89
- column
90
- key={i}
91
- className={classNames(
92
- 'list-group gm-block gm-margin-0 gm-border-0 gm-overflow-y',
93
- {
94
- 'gm-border-right': i !== list.length - 1
95
- }
96
- )}
97
- >
98
- {_.map(value, v => (
99
- <Flex
100
- key={v.value}
101
- title={v.name}
102
- justifyBetween
103
- onClick={handleSelect}
104
- onMouseEnter={() => handleMouseEnter(v._path)}
105
- className={classNames('list-group-item', {
106
- active: v.value === selected[i],
107
- hover: v.value === filterLastResultID
108
- })}
109
- id={v.value}
110
- >
111
- {v.name}&nbsp;
112
- {v.children && v.children.length && (
113
- <i className={classNames('gm-arrow-right')} />
114
- )}
115
- </Flex>
116
- ))}
117
- </Flex>
118
- ))}
119
- </Flex>
120
- )
121
- }
122
-
123
- Overlay.propTypes = {
124
- className: PropTypes.string,
125
- style: PropTypes.object,
126
- handleSelect: PropTypes.func.isRequired,
127
- handleMouseEnter: PropTypes.func.isRequired,
128
- list: PropTypes.array.isRequired,
129
- selected: PropTypes.array.isRequired,
130
- filterLastResultID: PropTypes.string.isRequired
131
- }
132
-
133
- class Cascader extends React.Component {
134
- constructor(props) {
135
- super(props)
136
-
137
- // deep clone data,然后给data生成_path数据
138
- const data = _.cloneDeep(props.data)
139
- mapPath(data)
140
-
141
- this.state = {
142
- selected: props.value ? [...props.value] : [], // 选中状态
143
- filterInput: null, // filtrable为true时,输入框的内容
144
- data: data,
145
- filterLastResultID: ''
146
- }
147
-
148
- this.handleClear = ::this.handleClear
149
- this.handleInputChange = ::this.handleInputChange
150
- this.handleKeyDown = ::this.handleKeyDown
151
- this.inputValueRender = ::this.inputValueRender
152
- this.setHoverStatus = _.debounce(selected => {
153
- this.setState({
154
- filterLastResultID: selected
155
- })
156
- }, 500)
157
- }
158
-
159
- UNSAFE_componentWillReceiveProps(nextProps) {
160
- if ('value' in nextProps) {
161
- this.setState({
162
- selected: nextProps.value ? [...nextProps.value] : []
163
- })
164
- }
165
-
166
- if (nextProps.data !== this.props.data) {
167
- const data = _.cloneDeep(nextProps.data)
168
- mapPath(data) // 给data生成_path数据
169
-
170
- this.setState({ data })
171
- }
172
- }
173
-
174
- getList() {
175
- const selected = this.state.selected
176
- const result = [this.state.data]
177
-
178
- _.each(selected, (value, i) => {
179
- const match = _.find(result[i], v => v.value === value)
180
- if (match) {
181
- if (match.children) {
182
- result.push(match.children)
183
- }
184
- }
185
- })
186
-
187
- return result
188
- }
189
-
190
- getFilterList(list, searchText) {
191
- return _.filter(list, item => {
192
- if (item.children) {
193
- item.children = this.getFilterList(item.children, searchText)
194
-
195
- if (item.children.length) {
196
- return true
197
- }
198
- }
199
-
200
- if (pinYinFilter([item], searchText, v => v.name).length) {
201
- return true
202
- }
203
-
204
- return false
205
- })
206
- }
207
-
208
- handleClear(e) {
209
- e.stopPropagation()
210
-
211
- this.setState({ selected: [] }, () => {
212
- this.handleSelect()
213
- })
214
- }
215
-
216
- handleSelect = () => {
217
- const { onlyChildSelectable } = this.props
218
- const { selected, data } = this.state
219
-
220
- const value = []
221
- if (selected.length > 0) {
222
- _.each(selected, (v, i) => {
223
- const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
224
- return v === val.value
225
- })
226
- value.push(match)
227
- })
228
- }
229
-
230
- // 如果选择有children的,则清空输入框
231
- if (
232
- onlyChildSelectable &&
233
- value.length &&
234
- value[value.length - 1].children
235
- ) {
236
- this.setState({ filterInput: '' })
237
- this.props.onChange([])
238
- } else {
239
- this.setState({ filterInput: null })
240
- this.props.onChange(selected)
241
- }
242
-
243
- // 选中后关闭cascader
244
- setTimeout(() => {
245
- window.document.body.click()
246
- }, 0)
247
-
248
- window.document.activeElement.blur() // blur input
249
- }
250
-
251
- handleMouseEnter = selected => {
252
- this.setState({ selected, filterLastResultID: '' })
253
- }
254
-
255
- handleInputChange(e) {
256
- const filterInput = e.target.value
257
-
258
- if (this.props.filtrable) {
259
- const { data } = this.state
260
- const selected = getMaxDeepPathOfMatchElement(data, filterInput)
261
- this.setState({
262
- filterInput,
263
- selected
264
- })
265
- this.setHoverStatus(selected.slice().reverse()[0])
266
- }
267
- }
268
-
269
- handleKeyDown(event) {
270
- const { keyCode } = event
271
-
272
- // 键盘上下键控制最当前选中列
273
- if (keyCode === 38 || keyCode === 40) {
274
- const listArr = this.getList()
275
- const selected = [...this.state.selected]
276
- const len = selected.length
277
-
278
- if (!len) {
279
- this.setState({
280
- selected: [listArr[0][0].value],
281
- filterInput: ''
282
- })
283
- return
284
- }
285
-
286
- const lastList = listArr[len - 1]
287
- const currentIndex = _.findIndex(
288
- lastList,
289
- item => item.value === selected[len - 1]
290
- )
291
-
292
- let lastValue = selected[len - 1]
293
-
294
- if (keyCode === 38 && currentIndex > 0) {
295
- lastValue = lastList[currentIndex - 1].value
296
- } else if (keyCode === 40 && currentIndex < lastList.length - 1) {
297
- lastValue = lastList[currentIndex + 1].value
298
- }
299
-
300
- selected[len - 1] = lastValue
301
-
302
- this.setState({
303
- selected
304
- })
305
- } else if (keyCode === 13) {
306
- // 键盘 回车
307
- this.handleSelect()
308
- }
309
- }
310
-
311
- inputValueRender() {
312
- const { filterInput, data } = this.state
313
- const { valueRender, filtrable } = this.props
314
- const selected = this.props.value || this.state.selected
315
-
316
- const value = []
317
- if (selected.length > 0) {
318
- _.each(selected, (v, i) => {
319
- const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
320
- return v === val.value
321
- })
322
- value.push(match)
323
- })
324
- }
325
-
326
- if (!filtrable) {
327
- return valueRender
328
- ? valueRender(value)
329
- : _.map(value, v => v.name).join(',')
330
- }
331
-
332
- return filterInput === null
333
- ? valueRender
334
- ? valueRender(value)
335
- : _.map(value, v => v?.name).join(',')
336
- : filterInput
337
- }
338
-
339
- renderChildren() {
340
- const { disabled } = this.props
341
- const { data } = this.state
342
- const inputValue = this.inputValueRender()
343
- let { inputProps } = this.props
344
-
345
- const selected = this.props.value || this.state.selected
346
- const value = []
347
- if (selected.length > 0) {
348
- _.each(selected, (v, i) => {
349
- const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
350
- return v === val.value
351
- })
352
- value.push(match)
353
- })
354
- }
355
-
356
- // disabled 的优先级比 inputProps的优先级高
357
- if (disabled) {
358
- inputProps = Object.assign({}, inputProps, { disabled })
359
- }
360
-
361
- return (
362
- <div
363
- className={classNames('gm-cascader', {
364
- 'gm-cascader-close': inputValue
365
- })}
366
- >
367
- <input
368
- {...inputProps}
369
- type='text'
370
- onChange={this.handleInputChange}
371
- onKeyDown={this.handleKeyDown}
372
- value={inputValue}
373
- className={classNames('form-control', inputProps.className)}
374
- />
375
- {inputValue && (
376
- <SVGCloseCircle
377
- onClick={this.handleClear}
378
- className='gm-cascader-icon gm-cascader-close-icon'
379
- />
380
- )}
381
- <SVGDownSmall className='gm-cascader-icon gm-cascader-down-small' />
382
- <SVGUpSmall className='gm-cascader-icon gm-cascader-up-small' />
383
- </div>
384
- )
385
- }
386
-
387
- render() {
388
- const { disabled, popoverStyle, value = [], style, className } = this.props
389
-
390
- return (
391
- <Popover
392
- animName
393
- style={popoverStyle}
394
- disabled={disabled}
395
- popup={
396
- <Overlay
397
- handleMouseEnter={this.handleMouseEnter}
398
- handleSelect={this.handleSelect}
399
- list={this.getList()}
400
- selected={value}
401
- style={style}
402
- className={className}
403
- filterLastResultID={this.state.filterLastResultID}
404
- />
405
- }
406
- >
407
- {this.props.children ? this.props.children : this.renderChildren()}
408
- </Popover>
409
- )
410
- }
411
- }
412
-
413
- Cascader.propTypes = {
414
- // 格式 [{value: 1, name: '深圳', children: [{...}]}]
415
- data: PropTypes.array.isRequired,
416
- // [1,2,...]
417
- value: PropTypes.array,
418
- // 同上
419
- defaultValue: PropTypes.array,
420
- // 会提供整个value回去
421
- onChange: PropTypes.func,
422
- // 没有this.props.children时有效
423
- inputProps: PropTypes.object,
424
- valueRender: PropTypes.func,
425
- children: PropTypes.any,
426
- disabled: PropTypes.bool,
427
- // 是否可搜索
428
- filtrable: PropTypes.bool,
429
- // 只允许选择子节点,有children则清空输入框
430
- onlyChildSelectable: PropTypes.bool,
431
- popoverStyle: PropTypes.object,
432
- className: PropTypes.string,
433
- style: PropTypes.object
434
- }
435
-
436
- Cascader.defaultProps = {
437
- onChange: _.noop,
438
- inputProps: {},
439
- disabled: false,
440
- onlyChildSelectable: false
441
- }
442
-
443
- export default Cascader
1
+ import React, { useEffect } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import _ from 'lodash'
4
+ import classNames from 'classnames'
5
+ import Flex from '../flex'
6
+ import Popover from '../popover'
7
+ import { pinYinFilter, pinyin } from '@gm-common/tool'
8
+ import SVGCloseCircle from '../../../svg/close-circle.svg'
9
+ import SVGDownSmall from '../../../svg/down.svg'
10
+ import SVGUpSmall from '../../../svg/up.svg'
11
+
12
+ // 给list中每个元素添加_path
13
+ function mapPath(list, searchText, parentPath = []) {
14
+ _.each(list, item => {
15
+ if (item._path === undefined) {
16
+ item._path = [...parentPath, item.value]
17
+ }
18
+
19
+ if (item.children) {
20
+ mapPath(item.children, searchText, [...item._path])
21
+ }
22
+ })
23
+ }
24
+
25
+ // 找出list树下匹配searchText的最深元素的路径
26
+ function getMaxDeepPathOfMatchElement(list, searchText) {
27
+ let maxLengthPath = []
28
+
29
+ function findMaxLengthPath(list, searchText) {
30
+ _.each(list, item => {
31
+ // 匹配首字母
32
+ const firstLetter = _.map(
33
+ pinyin(item.name, 'first_letter'),
34
+ value => value[0]
35
+ ).join('')
36
+ // 全拼集合
37
+ const normal = _.map(pinyin(item.name), value => value[0]).join('')
38
+
39
+ if (
40
+ (item.name.indexOf(searchText) > -1 ||
41
+ normal.indexOf(searchText) > -1 ||
42
+ firstLetter.indexOf(searchText) > -1) &&
43
+ maxLengthPath.length < item._path.length
44
+ ) {
45
+ maxLengthPath = item._path
46
+ }
47
+
48
+ if (item.children) {
49
+ findMaxLengthPath(item.children, searchText)
50
+ }
51
+ })
52
+ }
53
+
54
+ findMaxLengthPath(list, searchText)
55
+
56
+ return maxLengthPath
57
+ }
58
+
59
+ const Overlay = ({
60
+ className,
61
+ style,
62
+ selected,
63
+ list,
64
+ handleSelect,
65
+ handleMouseEnter,
66
+ filterLastResultID
67
+ }) => {
68
+ useEffect(() => {
69
+ _.each(selected, id => {
70
+ const $dom = document.getElementById(id)
71
+ $dom && $dom.scrollIntoViewIfNeeded()
72
+ })
73
+ }, [])
74
+
75
+ useEffect(() => {
76
+ if (filterLastResultID) {
77
+ const $dom = document.getElementById(filterLastResultID)
78
+ $dom && $dom.scrollIntoViewIfNeeded()
79
+ }
80
+ }, [filterLastResultID])
81
+
82
+ return (
83
+ <Flex
84
+ className={classNames('gm-cascader-list gm-bg', className)}
85
+ style={style}
86
+ >
87
+ {_.map(list, (value, i) => (
88
+ <Flex
89
+ column
90
+ key={i}
91
+ className={classNames(
92
+ 'list-group gm-block gm-margin-0 gm-border-0 gm-overflow-y',
93
+ {
94
+ 'gm-border-right': i !== list.length - 1
95
+ }
96
+ )}
97
+ >
98
+ {_.map(value, v => (
99
+ <Flex
100
+ key={v.value}
101
+ title={v.name}
102
+ justifyBetween
103
+ onClick={handleSelect}
104
+ onMouseEnter={() => handleMouseEnter(v._path)}
105
+ className={classNames('list-group-item', {
106
+ active: v.value === selected[i],
107
+ hover: v.value === filterLastResultID
108
+ })}
109
+ id={v.value}
110
+ >
111
+ {v.name}&nbsp;
112
+ {Array.isArray(v.children) && v.children.length > 0 && (
113
+ <i className={classNames('gm-arrow-right')} />
114
+ )}
115
+ </Flex>
116
+ ))}
117
+ </Flex>
118
+ ))}
119
+ </Flex>
120
+ )
121
+ }
122
+
123
+ Overlay.propTypes = {
124
+ className: PropTypes.string,
125
+ style: PropTypes.object,
126
+ handleSelect: PropTypes.func.isRequired,
127
+ handleMouseEnter: PropTypes.func.isRequired,
128
+ list: PropTypes.array.isRequired,
129
+ selected: PropTypes.array.isRequired,
130
+ filterLastResultID: PropTypes.string.isRequired
131
+ }
132
+
133
+ class Cascader extends React.Component {
134
+ constructor(props) {
135
+ super(props)
136
+
137
+ // deep clone data,然后给data生成_path数据
138
+ const data = _.cloneDeep(props.data)
139
+ mapPath(data)
140
+
141
+ this.state = {
142
+ selected: props.value ? [...props.value] : [], // 选中状态
143
+ filterInput: null, // filtrable为true时,输入框的内容
144
+ data: data,
145
+ filterLastResultID: ''
146
+ }
147
+
148
+ this.handleClear = ::this.handleClear
149
+ this.handleInputChange = ::this.handleInputChange
150
+ this.handleKeyDown = ::this.handleKeyDown
151
+ this.inputValueRender = ::this.inputValueRender
152
+ this.setHoverStatus = _.debounce(selected => {
153
+ this.setState({
154
+ filterLastResultID: selected
155
+ })
156
+ }, 500)
157
+ }
158
+
159
+ UNSAFE_componentWillReceiveProps(nextProps) {
160
+ if ('value' in nextProps) {
161
+ this.setState({
162
+ selected: nextProps.value ? [...nextProps.value] : []
163
+ })
164
+ }
165
+
166
+ if (nextProps.data !== this.props.data) {
167
+ const data = _.cloneDeep(nextProps.data)
168
+ mapPath(data) // 给data生成_path数据
169
+
170
+ this.setState({ data })
171
+ }
172
+ }
173
+
174
+ getList() {
175
+ const selected = this.state.selected
176
+ const result = [this.state.data]
177
+
178
+ _.each(selected, (value, i) => {
179
+ const match = _.find(result[i], v => v.value === value)
180
+ if (match) {
181
+ if (match.children) {
182
+ result.push(match.children)
183
+ }
184
+ }
185
+ })
186
+ return result
187
+ }
188
+
189
+ getFilterList(list, searchText) {
190
+ return _.filter(list, item => {
191
+ if (item.children) {
192
+ item.children = this.getFilterList(item.children, searchText)
193
+
194
+ if (item.children.length) {
195
+ return true
196
+ }
197
+ }
198
+
199
+ if (pinYinFilter([item], searchText, v => v.name).length) {
200
+ return true
201
+ }
202
+
203
+ return false
204
+ })
205
+ }
206
+
207
+ handleClear(e) {
208
+ e.stopPropagation()
209
+
210
+ this.setState({ selected: [] }, () => {
211
+ this.handleSelect()
212
+ })
213
+ }
214
+
215
+ handleSelect = () => {
216
+ const { onlyChildSelectable } = this.props
217
+ const { selected, data } = this.state
218
+
219
+ const value = []
220
+ if (selected.length > 0) {
221
+ _.each(selected, (v, i) => {
222
+ const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
223
+ return v === val.value
224
+ })
225
+ value.push(match)
226
+ })
227
+ }
228
+
229
+ // 如果选择有children的,则清空输入框
230
+ if (
231
+ onlyChildSelectable &&
232
+ value.length &&
233
+ value[value.length - 1].children
234
+ ) {
235
+ this.setState({ filterInput: '' })
236
+ this.props.onChange([])
237
+ } else {
238
+ this.setState({ filterInput: null })
239
+ this.props.onChange(selected)
240
+ }
241
+
242
+ // 选中后关闭cascader
243
+ setTimeout(() => {
244
+ window.document.body.click()
245
+ }, 0)
246
+
247
+ window.document.activeElement.blur() // blur input
248
+ }
249
+
250
+ handleMouseEnter = selected => {
251
+ this.setState({ selected, filterLastResultID: '' })
252
+ }
253
+
254
+ handleInputChange(e) {
255
+ const filterInput = e.target.value
256
+
257
+ if (this.props.filtrable) {
258
+ const { data } = this.state
259
+ const selected = getMaxDeepPathOfMatchElement(data, filterInput)
260
+ this.setState({
261
+ filterInput,
262
+ selected
263
+ })
264
+ this.setHoverStatus(selected.slice().reverse()[0])
265
+ }
266
+ }
267
+
268
+ handleKeyDown(event) {
269
+ const { keyCode } = event
270
+
271
+ // 键盘上下键控制最当前选中列
272
+ if (keyCode === 38 || keyCode === 40) {
273
+ const listArr = this.getList()
274
+ const selected = [...this.state.selected]
275
+ const len = selected.length
276
+
277
+ if (!len) {
278
+ this.setState({
279
+ selected: [listArr[0][0].value],
280
+ filterInput: ''
281
+ })
282
+ return
283
+ }
284
+
285
+ const lastList = listArr[len - 1]
286
+ const currentIndex = _.findIndex(
287
+ lastList,
288
+ item => item.value === selected[len - 1]
289
+ )
290
+
291
+ let lastValue = selected[len - 1]
292
+
293
+ if (keyCode === 38 && currentIndex > 0) {
294
+ lastValue = lastList[currentIndex - 1].value
295
+ } else if (keyCode === 40 && currentIndex < lastList.length - 1) {
296
+ lastValue = lastList[currentIndex + 1].value
297
+ }
298
+
299
+ selected[len - 1] = lastValue
300
+
301
+ this.setState({
302
+ selected
303
+ })
304
+ } else if (keyCode === 13) {
305
+ // 键盘 回车
306
+ this.handleSelect()
307
+ }
308
+ }
309
+
310
+ inputValueRender() {
311
+ const { filterInput, data } = this.state
312
+ const { valueRender, filtrable } = this.props
313
+ const selected = this.props.value || this.state.selected
314
+
315
+ const value = []
316
+ if (selected.length > 0) {
317
+ _.each(selected, (v, i) => {
318
+ const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
319
+ return v === val.value
320
+ })
321
+ value.push(match)
322
+ })
323
+ }
324
+
325
+ if (!filtrable) {
326
+ return valueRender
327
+ ? valueRender(value)
328
+ : _.map(value, v => v.name).join(',')
329
+ }
330
+
331
+ return filterInput === null
332
+ ? valueRender
333
+ ? valueRender(value)
334
+ : _.map(value, v => v?.name).join(',')
335
+ : filterInput
336
+ }
337
+
338
+ renderChildren() {
339
+ const { disabled } = this.props
340
+ const { data } = this.state
341
+ const inputValue = this.inputValueRender()
342
+ let { inputProps } = this.props
343
+ const selected = this.props.value || this.state.selected
344
+ const value = []
345
+ if (selected.length > 0) {
346
+ _.each(selected, (v, i) => {
347
+ const match = _.find(i === 0 ? data : value[i - 1]?.children, val => {
348
+ return v === val.value
349
+ })
350
+ value.push(match)
351
+ })
352
+ }
353
+
354
+ // disabled 的优先级比 inputProps的优先级高
355
+ if (disabled) {
356
+ inputProps = Object.assign({}, inputProps, { disabled })
357
+ }
358
+
359
+ return (
360
+ <div
361
+ className={classNames('gm-cascader', {
362
+ 'gm-cascader-close': inputValue
363
+ })}
364
+ >
365
+ <input
366
+ {...inputProps}
367
+ type='text'
368
+ onChange={this.handleInputChange}
369
+ onKeyDown={this.handleKeyDown}
370
+ value={inputValue}
371
+ className={classNames('form-control', inputProps.className)}
372
+ />
373
+ {inputValue && (
374
+ <SVGCloseCircle
375
+ onClick={this.handleClear}
376
+ className='gm-cascader-icon gm-cascader-close-icon'
377
+ />
378
+ )}
379
+ <SVGDownSmall className='gm-cascader-icon gm-cascader-down-small' />
380
+ <SVGUpSmall className='gm-cascader-icon gm-cascader-up-small' />
381
+ </div>
382
+ )
383
+ }
384
+
385
+ render() {
386
+ const { disabled, popoverStyle, value = [], style, className } = this.props
387
+
388
+ return (
389
+ <Popover
390
+ animName
391
+ style={popoverStyle}
392
+ disabled={disabled}
393
+ popup={
394
+ <Overlay
395
+ handleMouseEnter={this.handleMouseEnter}
396
+ handleSelect={this.handleSelect}
397
+ list={this.getList()}
398
+ selected={value}
399
+ style={style}
400
+ className={className}
401
+ filterLastResultID={this.state.filterLastResultID}
402
+ />
403
+ }
404
+ >
405
+ {this.props.children ? this.props.children : this.renderChildren()}
406
+ </Popover>
407
+ )
408
+ }
409
+ }
410
+
411
+ Cascader.propTypes = {
412
+ // 格式 [{value: 1, name: '深圳', children: [{...}]}]
413
+ data: PropTypes.array.isRequired,
414
+ // [1,2,...]
415
+ value: PropTypes.array,
416
+ // 同上
417
+ defaultValue: PropTypes.array,
418
+ // 会提供整个value回去
419
+ onChange: PropTypes.func,
420
+ // 没有this.props.children时有效
421
+ inputProps: PropTypes.object,
422
+ valueRender: PropTypes.func,
423
+ children: PropTypes.any,
424
+ disabled: PropTypes.bool,
425
+ // 是否可搜索
426
+ filtrable: PropTypes.bool,
427
+ // 只允许选择子节点,有children则清空输入框
428
+ onlyChildSelectable: PropTypes.bool,
429
+ popoverStyle: PropTypes.object,
430
+ className: PropTypes.string,
431
+ style: PropTypes.object
432
+ }
433
+
434
+ Cascader.defaultProps = {
435
+ onChange: _.noop,
436
+ inputProps: {},
437
+ disabled: false,
438
+ onlyChildSelectable: false
439
+ }
440
+
441
+ export default Cascader