@gmfe/react 2.14.17 → 2.14.19-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 (376) hide show
  1. package/package.json +3 -3
  2. package/src/common/hooks/index.js +3 -3
  3. package/src/common/hooks/use_mutation_observer.js +25 -25
  4. package/src/common/util.js +52 -52
  5. package/src/component/affix/affix.stories.js +13 -13
  6. package/src/component/affix/index.js +21 -21
  7. package/src/component/box/box.js +31 -31
  8. package/src/component/box/box.stories.js +94 -94
  9. package/src/component/box/box_form.js +77 -77
  10. package/src/component/box/box_panel.js +91 -91
  11. package/src/component/box/box_table.js +51 -51
  12. package/src/component/box/index.js +6 -6
  13. package/src/component/box/style.less +39 -39
  14. package/src/component/button/button.stories.js +91 -91
  15. package/src/component/button/index.js +92 -92
  16. package/src/component/button/style.less +114 -114
  17. package/src/component/calendar/calendar.js +52 -52
  18. package/src/component/calendar/calendar.stories.js +57 -57
  19. package/src/component/calendar/content.js +89 -89
  20. package/src/component/calendar/day.js +109 -109
  21. package/src/component/calendar/head.js +243 -243
  22. package/src/component/calendar/index.js +4 -4
  23. package/src/component/calendar/range_calendar.js +150 -150
  24. package/src/component/calendar/style.less +140 -140
  25. package/src/component/calendar/week.js +27 -27
  26. package/src/component/carousel/carousel.js +178 -178
  27. package/src/component/carousel/stories.js +50 -50
  28. package/src/component/carousel/style.less +48 -48
  29. package/src/component/cascader/cascader.js +443 -443
  30. package/src/component/cascader/cascader.select.js +195 -195
  31. package/src/component/cascader/stories.js +240 -240
  32. package/src/component/cascader/style.less +122 -122
  33. package/src/component/checkbox/checkbox.js +86 -86
  34. package/src/component/checkbox/checkbox_group.js +66 -66
  35. package/src/component/checkbox/index.js +4 -4
  36. package/src/component/checkbox/stories.js +103 -103
  37. package/src/component/checkbox/style.less +88 -88
  38. package/src/component/collapse/collapse.stories.js +18 -18
  39. package/src/component/collapse/index.js +36 -36
  40. package/src/component/color_picker/index.js +190 -190
  41. package/src/component/color_picker/stories.js +17 -17
  42. package/src/component/color_picker/style.less +41 -41
  43. package/src/component/date_picker/date_picker.stories.js +102 -102
  44. package/src/component/date_picker/index.js +217 -217
  45. package/src/component/date_picker/overlay.js +119 -119
  46. package/src/component/date_picker/style.less +22 -22
  47. package/src/component/date_picker/time_select.js +62 -62
  48. package/src/component/date_range_picker/date_range_picker.stories.js +196 -196
  49. package/src/component/date_range_picker/index.js +206 -206
  50. package/src/component/date_range_picker/left.js +127 -127
  51. package/src/component/date_range_picker/overlay.js +202 -202
  52. package/src/component/date_range_picker/style.less +46 -46
  53. package/src/component/date_range_picker/time_range_select.js +150 -150
  54. package/src/component/date_range_picker/two.js +129 -129
  55. package/src/component/date_range_picker/util.js +42 -42
  56. package/src/component/dialog/index.js +240 -240
  57. package/src/component/dialog/stories.js +125 -125
  58. package/src/component/divider/index.js +28 -28
  59. package/src/component/divider/stories.js +5 -5
  60. package/src/component/divider/style.less +15 -15
  61. package/src/component/drawer/index.js +107 -107
  62. package/src/component/drawer/style.less +43 -43
  63. package/src/component/drop_down/drop_down.js +84 -84
  64. package/src/component/drop_down/drop_down_item.js +43 -43
  65. package/src/component/drop_down/drop_down_items.js +22 -22
  66. package/src/component/drop_down/index.js +5 -5
  67. package/src/component/drop_down/stories.js +38 -38
  68. package/src/component/drop_down/style.less +21 -21
  69. package/src/component/drop_select/index.js +208 -208
  70. package/src/component/drop_select/style.less +69 -69
  71. package/src/component/dropper/index.js +62 -62
  72. package/src/component/dropper/style.less +18 -18
  73. package/src/component/editable_text/editable_text.stories.js +47 -47
  74. package/src/component/editable_text/index.js +106 -106
  75. package/src/component/editable_text/style.less +29 -29
  76. package/src/component/filter_select/filter.select.js +416 -416
  77. package/src/component/filter_select/multiple.filter.select.js +425 -425
  78. package/src/component/filter_select/style.less +117 -117
  79. package/src/component/flex/index.js +132 -132
  80. package/src/component/flex/stories.js +13 -13
  81. package/src/component/flex/style.less +101 -101
  82. package/src/component/flip_number/index.js +196 -196
  83. package/src/component/flip_number/stories.js +25 -25
  84. package/src/component/flip_number/utils.js +50 -50
  85. package/src/component/form/form.js +153 -153
  86. package/src/component/form/form.stories.js +553 -553
  87. package/src/component/form/form_block.js +59 -59
  88. package/src/component/form/form_button.js +29 -29
  89. package/src/component/form/form_group.js +173 -173
  90. package/src/component/form/form_item.js +163 -163
  91. package/src/component/form/form_panel.js +71 -71
  92. package/src/component/form/index.js +8 -8
  93. package/src/component/form/style.less +130 -130
  94. package/src/component/form/util.js +13 -13
  95. package/src/component/function_set/function_set.stories.js +91 -91
  96. package/src/component/function_set/index.js +98 -98
  97. package/src/component/function_set/overlay.js +56 -56
  98. package/src/component/grid/col.js +72 -72
  99. package/src/component/grid/grid.stories.js +123 -123
  100. package/src/component/grid/index.js +4 -4
  101. package/src/component/grid/mixin.less +48 -48
  102. package/src/component/grid/row.js +44 -44
  103. package/src/component/grid/style.less +26 -26
  104. package/src/component/grid/util.js +11 -11
  105. package/src/component/icon_down_up/index.js +28 -28
  106. package/src/component/icon_down_up/stories.js +18 -18
  107. package/src/component/icon_down_up/style.less +8 -8
  108. package/src/component/image_preview/index.js +20 -20
  109. package/src/component/image_preview/preview_modal.js +193 -193
  110. package/src/component/image_preview/style.less +119 -119
  111. package/src/component/img_uploader/index.js +149 -149
  112. package/src/component/img_uploader/index.stories.js +51 -51
  113. package/src/component/img_uploader/style.less +22 -22
  114. package/src/component/input/index.js +19 -19
  115. package/src/component/input_number/index.js +73 -73
  116. package/src/component/input_number/number.js +158 -158
  117. package/src/component/input_number/stories.js +21 -21
  118. package/src/component/input_number/style.less +10 -10
  119. package/src/component/layout_root/index.js +165 -165
  120. package/src/component/lazy_img/index.js +68 -68
  121. package/src/component/level_list/index.js +120 -120
  122. package/src/component/level_list/level_item.js +64 -64
  123. package/src/component/level_list/level_list.stories.js +139 -139
  124. package/src/component/level_list/style.less +47 -47
  125. package/src/component/level_list/util.js +22 -22
  126. package/src/component/level_select/index.js +240 -240
  127. package/src/component/level_select/level_select.stories.js +67 -67
  128. package/src/component/list/base.js +155 -155
  129. package/src/component/list/index.js +93 -93
  130. package/src/component/list/list.stories.js +99 -99
  131. package/src/component/list/style.less +58 -58
  132. package/src/component/loading/index.js +45 -45
  133. package/src/component/loading/loading_chunk.js +59 -59
  134. package/src/component/loading/loading_full_screen.js +62 -62
  135. package/src/component/loading/stories.js +46 -46
  136. package/src/component/loading/style.less +92 -92
  137. package/src/component/mask/index.js +34 -34
  138. package/src/component/mask/style.less +10 -10
  139. package/src/component/modal/clean_modal.js +36 -36
  140. package/src/component/modal/index.js +293 -293
  141. package/src/component/modal/right_side_modal.js +37 -37
  142. package/src/component/modal/stories.js +96 -96
  143. package/src/component/modal/style.less +145 -145
  144. package/src/component/more_select/base.js +517 -517
  145. package/src/component/more_select/index.js +91 -91
  146. package/src/component/more_select/stories.js +261 -261
  147. package/src/component/more_select/style.less +130 -130
  148. package/src/component/nav/index.js +269 -269
  149. package/src/component/nav/nav.stories.js +133 -133
  150. package/src/component/nav/style.less +156 -156
  151. package/src/component/nprogress/index.js +34 -34
  152. package/src/component/nprogress/stories.js +22 -22
  153. package/src/component/nprogress/style.less +39 -39
  154. package/src/component/pagination/base.js +67 -67
  155. package/src/component/pagination/left.js +65 -65
  156. package/src/component/pagination/page.js +120 -120
  157. package/src/component/pagination/page_peek.js +96 -96
  158. package/src/component/pagination/pagination.js +54 -54
  159. package/src/component/pagination/pagination.stories.js +104 -104
  160. package/src/component/pagination/pagination_text.js +71 -71
  161. package/src/component/pagination/pagination_v2.js +30 -30
  162. package/src/component/pagination/right.js +67 -67
  163. package/src/component/pagination/style.less +52 -52
  164. package/src/component/pagination/util.js +5 -5
  165. package/src/component/picture_preview/index.js +21 -21
  166. package/src/component/popover/index.js +373 -373
  167. package/src/component/popover/stories.js +101 -101
  168. package/src/component/popup/index.js +4 -4
  169. package/src/component/popup/popup.js +172 -172
  170. package/src/component/popup/popup_content_confirm.js +67 -67
  171. package/src/component/popup/style.less +105 -105
  172. package/src/component/price/index.js +147 -147
  173. package/src/component/price/stories.js +34 -34
  174. package/src/component/progress/index.js +101 -101
  175. package/src/component/progress/stories.js +60 -60
  176. package/src/component/progress/style.less +88 -88
  177. package/src/component/progress_circle/index.js +116 -116
  178. package/src/component/progress_circle/stories.js +54 -54
  179. package/src/component/progress_circle/style.less +17 -17
  180. package/src/component/radio/index.js +4 -4
  181. package/src/component/radio/radio.js +76 -76
  182. package/src/component/radio/radio_group.js +51 -51
  183. package/src/component/radio/stories.js +80 -80
  184. package/src/component/radio/style.less +63 -63
  185. package/src/component/recommend_input/index.js +118 -118
  186. package/src/component/recommend_input/recommend_input.stories.js +56 -56
  187. package/src/component/recommend_input/style.less +25 -25
  188. package/src/component/select/index.js +4 -4
  189. package/src/component/select/option.js +22 -22
  190. package/src/component/select/select.js +186 -186
  191. package/src/component/select/select.stories.js +79 -79
  192. package/src/component/select/style.less +4 -4
  193. package/src/component/selection/index.js +132 -132
  194. package/src/component/selection/selection.stories.js +41 -41
  195. package/src/component/selection/style.less +67 -67
  196. package/src/component/sheet/index.js +7 -7
  197. package/src/component/sheet/sheet.js +348 -348
  198. package/src/component/sheet/sheet_action.js +16 -16
  199. package/src/component/sheet/sheet_batch_action.js +16 -16
  200. package/src/component/sheet/sheet_column.js +21 -21
  201. package/src/component/sheet/sheet_select.js +31 -31
  202. package/src/component/sheet/stories.js +210 -210
  203. package/src/component/sheet/style.less +95 -95
  204. package/src/component/steps/index.js +66 -66
  205. package/src/component/steps/steps.stories.js +15 -15
  206. package/src/component/steps/style.less +39 -39
  207. package/src/component/storage/index.js +54 -54
  208. package/src/component/storage/stories.js +38 -38
  209. package/src/component/switch/index.js +118 -118
  210. package/src/component/switch/stories.js +7 -7
  211. package/src/component/switch/style.less +70 -70
  212. package/src/component/table_select/index.js +152 -152
  213. package/src/component/table_select/style.less +12 -12
  214. package/src/component/table_select/table_select.stories.js +91 -91
  215. package/src/component/table_select/util.js +21 -21
  216. package/src/component/tabs/style.less +33 -33
  217. package/src/component/tabs/tabs.js +97 -97
  218. package/src/component/tabs/tabs.stories.js +48 -48
  219. package/src/component/time_span/style.less +45 -45
  220. package/src/component/time_span/time_span.js +183 -183
  221. package/src/component/time_span/time_span.stories.js +66 -66
  222. package/src/component/time_span/time_span_picker.js +112 -112
  223. package/src/component/time_span/time_span_picker.stories.js +71 -71
  224. package/src/component/tip/index.js +168 -168
  225. package/src/component/tip/stories.js +54 -54
  226. package/src/component/tip/style.less +41 -41
  227. package/src/component/tool_tip/index.js +58 -58
  228. package/src/component/tool_tip/stories.js +36 -36
  229. package/src/component/transfer/box.js +186 -141
  230. package/src/component/transfer/index.js +4 -4
  231. package/src/component/transfer/stories.js +108 -118
  232. package/src/component/transfer/style.less +34 -34
  233. package/src/component/transfer/transfer.js +181 -173
  234. package/src/component/transfer/transfer_group.js +178 -178
  235. package/src/component/transfer_v2/index.js +171 -171
  236. package/src/component/transfer_v2/transfer_v2.stories.js +226 -226
  237. package/src/component/tree/bottom.js +41 -41
  238. package/src/component/tree/index.js +205 -205
  239. package/src/component/tree/item.js +154 -154
  240. package/src/component/tree/list.js +151 -151
  241. package/src/component/tree/style.less +147 -147
  242. package/src/component/tree/tree.stories.js +241 -241
  243. package/src/component/tree/util.js +24 -24
  244. package/src/component/tree_v2/bottom.js +40 -40
  245. package/src/component/tree_v2/index.js +260 -260
  246. package/src/component/tree_v2/list.js +230 -230
  247. package/src/component/tree_v2/style.less +38 -38
  248. package/src/component/tree_v2/tree.stories.js +419 -419
  249. package/src/component/tree_v2/util.js +185 -185
  250. package/src/component/uploader/index.js +108 -108
  251. package/src/component/uploader/style.less +24 -24
  252. package/src/component/uploader/uploader.stories.js +51 -51
  253. package/src/css/arrow.less +56 -56
  254. package/src/css/bg.less +52 -52
  255. package/src/css/border.less +40 -40
  256. package/src/css/cover.less +236 -236
  257. package/src/css/cursor.less +19 -19
  258. package/src/css/display.less +16 -16
  259. package/src/css/distance.less +324 -324
  260. package/src/css/error.less +10 -10
  261. package/src/css/other.less +16 -16
  262. package/src/css/overflow.less +23 -23
  263. package/src/css/position.less +11 -11
  264. package/src/css/rotate.less +28 -28
  265. package/src/css/shadow.less +11 -11
  266. package/src/css/stories.js +104 -104
  267. package/src/css/svg.less +51 -51
  268. package/src/css/text.less +120 -120
  269. package/src/css/variables.less +62 -62
  270. package/src/event_type.js +16 -16
  271. package/src/fonts/glyphicons-halflings-regular.svg +542 -542
  272. package/src/index.js +237 -237
  273. package/src/index.less +108 -108
  274. package/src/less/.csscomb.json +304 -304
  275. package/src/less/.csslintrc +19 -19
  276. package/src/less/alerts.less +72 -72
  277. package/src/less/badges.less +65 -65
  278. package/src/less/bootstrap.less +51 -51
  279. package/src/less/breadcrumbs.less +25 -25
  280. package/src/less/button-groups.less +253 -253
  281. package/src/less/buttons.less +186 -186
  282. package/src/less/carousel.less +269 -269
  283. package/src/less/close.less +33 -33
  284. package/src/less/code.less +68 -68
  285. package/src/less/component-animations.less +39 -39
  286. package/src/less/custom.less +37 -37
  287. package/src/less/dropdowns.less +215 -215
  288. package/src/less/forms.less +612 -612
  289. package/src/less/glyphicons.less +1614 -1614
  290. package/src/less/grid.less +76 -76
  291. package/src/less/input-groups.less +175 -175
  292. package/src/less/jumbotron.less +53 -53
  293. package/src/less/labels.less +64 -64
  294. package/src/less/list-group.less +126 -126
  295. package/src/less/media.less +66 -66
  296. package/src/less/mixins/alerts.less +14 -14
  297. package/src/less/mixins/background-variant.less +9 -9
  298. package/src/less/mixins/border-radius.less +21 -21
  299. package/src/less/mixins/buttons.less +65 -65
  300. package/src/less/mixins/center-block.less +7 -7
  301. package/src/less/mixins/clearfix.less +22 -22
  302. package/src/less/mixins/forms.less +84 -84
  303. package/src/less/mixins/gradients.less +59 -59
  304. package/src/less/mixins/grid-framework.less +96 -96
  305. package/src/less/mixins/grid.less +134 -134
  306. package/src/less/mixins/hide-text.less +21 -21
  307. package/src/less/mixins/image.less +25 -25
  308. package/src/less/mixins/labels.less +12 -12
  309. package/src/less/mixins/list-group.less +30 -30
  310. package/src/less/mixins/nav-divider.less +10 -10
  311. package/src/less/mixins/nav-vertical-align.less +9 -9
  312. package/src/less/mixins/opacity.less +8 -8
  313. package/src/less/mixins/pagination.less +24 -24
  314. package/src/less/mixins/panels.less +24 -24
  315. package/src/less/mixins/progress-bar.less +10 -10
  316. package/src/less/mixins/reset-filter.less +8 -8
  317. package/src/less/mixins/reset-text.less +18 -18
  318. package/src/less/mixins/resize.less +6 -6
  319. package/src/less/mixins/responsive-visibility.less +21 -21
  320. package/src/less/mixins/size.less +10 -10
  321. package/src/less/mixins/tab-focus.less +9 -9
  322. package/src/less/mixins/table-row.less +28 -28
  323. package/src/less/mixins/text-emphasis.less +9 -9
  324. package/src/less/mixins/text-overflow.less +8 -8
  325. package/src/less/mixins/vendor-prefixes.less +254 -254
  326. package/src/less/mixins.less +36 -36
  327. package/src/less/modals.less +163 -163
  328. package/src/less/navbar.less +651 -651
  329. package/src/less/navs.less +236 -236
  330. package/src/less/normalize.less +424 -424
  331. package/src/less/pager.less +54 -54
  332. package/src/less/pagination.less +90 -90
  333. package/src/less/panels.less +274 -274
  334. package/src/less/popovers.less +140 -140
  335. package/src/less/print.less +103 -103
  336. package/src/less/progress-bars.less +92 -92
  337. package/src/less/responsive-embed.less +35 -35
  338. package/src/less/responsive-utilities.less +209 -209
  339. package/src/less/scaffolding.less +154 -154
  340. package/src/less/tables.less +228 -228
  341. package/src/less/theme.less +344 -344
  342. package/src/less/thumbnails.less +35 -35
  343. package/src/less/tooltip.less +115 -115
  344. package/src/less/type.less +352 -352
  345. package/src/less/utilities.less +57 -57
  346. package/src/less/variables.less +833 -833
  347. package/src/less/wells.less +29 -29
  348. package/src/sotries.js +4 -4
  349. package/src/validator/index.js +10 -10
  350. package/src/validator/rules.js +66 -66
  351. package/src/validator/type.js +10 -10
  352. package/src/validator/validator.js +86 -86
  353. package/src/var.less +4 -4
  354. package/svg/calendar-month.svg +8 -8
  355. package/svg/calendar-year.svg +13 -13
  356. package/svg/calendar.svg +17 -17
  357. package/svg/check-detail.svg +18 -18
  358. package/svg/close-circle.svg +13 -13
  359. package/svg/closeup.svg +20 -20
  360. package/svg/delete.svg +10 -10
  361. package/svg/down-small.svg +1 -1
  362. package/svg/down.svg +1 -1
  363. package/svg/edit-box.svg +17 -17
  364. package/svg/edit-pen.svg +17 -17
  365. package/svg/empty.svg +27 -27
  366. package/svg/expand.svg +21 -21
  367. package/svg/left-small.svg +1 -1
  368. package/svg/more.svg +10 -10
  369. package/svg/next.svg +40 -40
  370. package/svg/pen.svg +12 -12
  371. package/svg/remove.svg +1 -1
  372. package/svg/right-small.svg +1 -1
  373. package/svg/search.svg +8 -8
  374. package/svg/setting.svg +17 -17
  375. package/svg/up-small.svg +1 -1
  376. package/svg/up.svg +1 -1
@@ -1,443 +1,443 @@
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
+ {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