iov-design 2.15.60 → 2.15.61

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 (234) hide show
  1. package/README.md +148 -148
  2. package/lib/alert.js +24 -105
  3. package/lib/aside.js +24 -34
  4. package/lib/autocomplete.js +36 -240
  5. package/lib/avatar.js +21 -20
  6. package/lib/backtop.js +27 -52
  7. package/lib/badge.js +30 -58
  8. package/lib/breadcrumb-item.js +24 -53
  9. package/lib/breadcrumb.js +24 -37
  10. package/lib/button-group.js +24 -29
  11. package/lib/button.js +38 -60
  12. package/lib/calendar.js +29 -146
  13. package/lib/card.js +24 -51
  14. package/lib/carousel-item.js +30 -68
  15. package/lib/carousel.js +27 -159
  16. package/lib/cascader-panel.js +41 -64
  17. package/lib/cascader.js +37 -470
  18. package/lib/checkbox-button.js +28 -164
  19. package/lib/checkbox-group.js +24 -37
  20. package/lib/checkbox.js +35 -189
  21. package/lib/col.js +1 -0
  22. package/lib/collapse-item.js +27 -125
  23. package/lib/collapse.js +24 -37
  24. package/lib/color-picker.js +104 -424
  25. package/lib/container.js +24 -34
  26. package/lib/date-picker.js +126 -1981
  27. package/lib/descriptions-item.js +1 -0
  28. package/lib/descriptions.js +1 -0
  29. package/lib/dialog.js +24 -137
  30. package/lib/divider.js +29 -64
  31. package/lib/drawer.js +24 -139
  32. package/lib/dropdown-item.js +27 -45
  33. package/lib/dropdown-menu.js +24 -51
  34. package/lib/dropdown.js +21 -20
  35. package/lib/empty.js +24 -61
  36. package/lib/footer.js +24 -34
  37. package/lib/form-item.js +42 -128
  38. package/lib/form.js +27 -40
  39. package/lib/header.js +24 -34
  40. package/lib/icon.js +24 -29
  41. package/lib/image.js +36 -220
  42. package/lib/index.js +1 -1
  43. package/lib/infinite-scroll.js +1 -0
  44. package/lib/input-number.js +30 -163
  45. package/lib/input.js +42 -274
  46. package/lib/iov-design.common.js +1635 -11132
  47. package/lib/link.js +31 -56
  48. package/lib/loading.js +24 -77
  49. package/lib/locale/format.js +10 -10
  50. package/lib/main.js +24 -29
  51. package/lib/menu-item-group.js +24 -40
  52. package/lib/menu-item.js +27 -83
  53. package/lib/menu.js +21 -20
  54. package/lib/message-box.js +24 -321
  55. package/lib/message.js +30 -82
  56. package/lib/mixins/migrating.js +20 -20
  57. package/lib/notification.js +24 -109
  58. package/lib/option-group.js +24 -50
  59. package/lib/option.js +27 -76
  60. package/lib/page-header.js +24 -56
  61. package/lib/pagination.js +24 -97
  62. package/lib/popconfirm.js +24 -97
  63. package/lib/popover.js +24 -89
  64. package/lib/progress.js +30 -133
  65. package/lib/radio-button.js +29 -111
  66. package/lib/radio-group.js +24 -39
  67. package/lib/radio.js +36 -152
  68. package/lib/rate.js +24 -94
  69. package/lib/result.js +72 -187
  70. package/lib/row.js +1 -0
  71. package/lib/scrollbar.js +1 -0
  72. package/lib/select.js +48 -637
  73. package/lib/skeleton-item.js +36 -68
  74. package/lib/skeleton.js +28 -70
  75. package/lib/slider.js +36 -267
  76. package/lib/spinner.js +24 -51
  77. package/lib/statistic.js +24 -76
  78. package/lib/step.js +29 -118
  79. package/lib/steps.js +27 -40
  80. package/lib/submenu.js +21 -20
  81. package/lib/switch.js +24 -130
  82. package/lib/tab-pane.js +24 -52
  83. package/lib/table-column.js +1 -0
  84. package/lib/table.js +93 -633
  85. package/lib/tabs.js +34 -49
  86. package/lib/tag.js +21 -20
  87. package/lib/theme-chalk/button.css +1 -1
  88. package/lib/theme-chalk/calendar.css +1 -1
  89. package/lib/theme-chalk/dropdown.css +1 -1
  90. package/lib/theme-chalk/index.css +1 -1
  91. package/lib/theme-chalk/link.css +1 -1
  92. package/lib/theme-chalk/message-box.css +1 -1
  93. package/lib/theme-chalk/transfer.css +1 -1
  94. package/lib/time-picker.js +58 -820
  95. package/lib/time-select.js +42 -303
  96. package/lib/timeline-item.js +29 -75
  97. package/lib/timeline.js +21 -20
  98. package/lib/tooltip.js +1 -0
  99. package/lib/transfer.js +36 -299
  100. package/lib/tree.js +54 -243
  101. package/lib/upload.js +86 -654
  102. package/lib/utils/clickoutside.js +7 -7
  103. package/lib/utils/vue-popper.js +7 -7
  104. package/package.json +154 -154
  105. package/packages/autocomplete/src/autocomplete-suggestions.vue +76 -76
  106. package/packages/autocomplete/src/autocomplete.vue +285 -285
  107. package/packages/button/src/button.vue +90 -90
  108. package/packages/calendar/src/date-table.vue +200 -200
  109. package/packages/calendar/src/main.vue +280 -280
  110. package/packages/carousel/src/item.vue +138 -138
  111. package/packages/carousel/src/main.vue +315 -315
  112. package/packages/cascader/src/cascader.vue +776 -776
  113. package/packages/cascader-panel/src/cascader-menu.vue +138 -138
  114. package/packages/cascader-panel/src/cascader-node.vue +246 -246
  115. package/packages/cascader-panel/src/cascader-panel.vue +391 -391
  116. package/packages/cascader-panel/src/node.js +166 -166
  117. package/packages/cascader-panel/src/store.js +58 -58
  118. package/packages/checkbox/src/checkbox-button.vue +199 -199
  119. package/packages/checkbox/src/checkbox-group.vue +49 -49
  120. package/packages/checkbox/src/checkbox.vue +225 -225
  121. package/packages/collapse/src/collapse-item.vue +114 -114
  122. package/packages/color-picker/src/components/picker-dropdown.vue +121 -121
  123. package/packages/color-picker/src/main.vue +188 -188
  124. package/packages/date-picker/src/basic/date-table.vue +441 -441
  125. package/packages/date-picker/src/basic/month-table.vue +269 -269
  126. package/packages/date-picker/src/basic/time-spinner.vue +304 -304
  127. package/packages/date-picker/src/basic/year-table.vue +111 -111
  128. package/packages/date-picker/src/panel/date-range.vue +680 -680
  129. package/packages/date-picker/src/panel/date.vue +609 -609
  130. package/packages/date-picker/src/panel/month-range.vue +289 -289
  131. package/packages/date-picker/src/panel/time-range.vue +248 -248
  132. package/packages/date-picker/src/panel/time-select.vue +178 -178
  133. package/packages/date-picker/src/panel/time.vue +186 -186
  134. package/packages/date-picker/src/picker.vue +967 -967
  135. package/packages/descriptions/src/index.js +180 -180
  136. package/packages/dialog/src/component.vue +262 -262
  137. package/packages/drawer/src/main.vue +205 -205
  138. package/packages/dropdown/src/dropdown-item.vue +37 -37
  139. package/packages/dropdown/src/dropdown-menu.vue +63 -63
  140. package/packages/dropdown/src/dropdown.vue +293 -293
  141. package/packages/empty/src/index.vue +70 -70
  142. package/packages/form/src/form-item.vue +324 -324
  143. package/packages/form/src/form.vue +182 -182
  144. package/packages/image/src/image-viewer.vue +330 -330
  145. package/packages/image/src/main.vue +249 -249
  146. package/packages/infinite-scroll/src/main.js +150 -150
  147. package/packages/input/src/input.vue +477 -477
  148. package/packages/input-number/src/input-number.vue +283 -283
  149. package/packages/loading/src/directive.js +133 -133
  150. package/packages/loading/src/index.js +106 -106
  151. package/packages/menu/src/menu-item.vue +112 -112
  152. package/packages/menu/src/menu.vue +325 -325
  153. package/packages/menu/src/submenu.vue +349 -349
  154. package/packages/message/src/main.js +91 -91
  155. package/packages/message-box/src/main.js +216 -216
  156. package/packages/message-box/src/main.vue +333 -333
  157. package/packages/notification/src/main.js +94 -94
  158. package/packages/page-header/src/main.vue +30 -30
  159. package/packages/pagination/src/pagination.js +390 -390
  160. package/packages/popconfirm/src/main.vue +104 -104
  161. package/packages/popover/src/main.vue +239 -239
  162. package/packages/radio/src/radio-button.vue +115 -115
  163. package/packages/radio/src/radio-group.vue +115 -115
  164. package/packages/radio/src/radio.vue +148 -148
  165. package/packages/rate/src/main.vue +348 -348
  166. package/packages/scrollbar/src/bar.js +92 -92
  167. package/packages/scrollbar/src/main.js +130 -130
  168. package/packages/select/src/option-group.vue +60 -60
  169. package/packages/select/src/option.vue +171 -171
  170. package/packages/select/src/select-dropdown.vue +74 -74
  171. package/packages/select/src/select.vue +979 -979
  172. package/packages/slider/src/button.vue +238 -238
  173. package/packages/slider/src/main.vue +427 -427
  174. package/packages/statistic/src/main.vue +204 -204
  175. package/packages/steps/src/steps.vue +68 -68
  176. package/packages/switch/src/component.vue +182 -182
  177. package/packages/table/src/config.js +153 -153
  178. package/packages/table/src/filter-panel.vue +194 -194
  179. package/packages/table/src/store/current.js +76 -76
  180. package/packages/table/src/store/helper.js +41 -41
  181. package/packages/table/src/store/index.js +147 -147
  182. package/packages/table/src/store/watcher.js +502 -502
  183. package/packages/table/src/table-body.js +469 -469
  184. package/packages/table/src/table-column.js +328 -328
  185. package/packages/table/src/table-header.js +571 -571
  186. package/packages/table/src/table-layout.js +249 -249
  187. package/packages/table/src/table-row.js +101 -101
  188. package/packages/table/src/table.vue +740 -740
  189. package/packages/table/src/util.js +273 -273
  190. package/packages/tabs/src/tab-bar.vue +57 -57
  191. package/packages/tabs/src/tab-nav.vue +294 -294
  192. package/packages/tabs/src/tabs.vue +201 -201
  193. package/packages/theme-chalk/src/button.scss +416 -416
  194. package/packages/theme-chalk/src/cascader.scss +252 -252
  195. package/packages/theme-chalk/src/checkbox.scss +419 -419
  196. package/packages/theme-chalk/src/common/var.scss +795 -795
  197. package/packages/theme-chalk/src/form.scss +201 -201
  198. package/packages/theme-chalk/src/input.scss +591 -591
  199. package/packages/theme-chalk/src/iovfont.scss +803 -803
  200. package/packages/theme-chalk/src/link.scss +8 -8
  201. package/packages/theme-chalk/src/message-box.scss +207 -207
  202. package/packages/theme-chalk/src/mixins/_button.scss +136 -136
  203. package/packages/theme-chalk/src/mixins/mixins.scss +190 -190
  204. package/packages/theme-chalk/src/radio-button.scss +115 -115
  205. package/packages/theme-chalk/src/select.scss +270 -270
  206. package/packages/theme-chalk/src/tabs.scss +755 -755
  207. package/packages/theme-chalk/src/upload.scss +568 -568
  208. package/packages/tooltip/src/main.js +242 -242
  209. package/packages/transfer/src/main.vue +231 -231
  210. package/packages/transfer/src/transfer-panel.vue +251 -251
  211. package/packages/tree/src/model/node.js +484 -484
  212. package/packages/tree/src/tree-node.vue +279 -279
  213. package/packages/tree/src/tree.vue +496 -496
  214. package/packages/upload/src/index.vue +420 -420
  215. package/packages/upload/src/upload-file.vue +98 -98
  216. package/packages/upload/src/upload-list.vue +115 -115
  217. package/packages/upload/src/upload-picture.vue +98 -98
  218. package/packages/upload/src/upload.vue +231 -231
  219. package/packages/upload/src/utils.js +31 -31
  220. package/src/directives/repeat-click.js +26 -26
  221. package/src/index.js +259 -259
  222. package/src/locale/format.js +46 -46
  223. package/src/locale/index.js +48 -48
  224. package/src/locale/lang/lo-LA.js +126 -126
  225. package/src/mixins/locale.js +9 -9
  226. package/src/mixins/migrating.js +54 -54
  227. package/src/transitions/collapse-transition.js +77 -77
  228. package/src/utils/clickoutside.js +76 -76
  229. package/src/utils/date-util.js +282 -282
  230. package/src/utils/popup/index.js +218 -218
  231. package/src/utils/popup/popup-manager.js +194 -194
  232. package/src/utils/util.js +245 -245
  233. package/src/utils/vdom.js +5 -5
  234. package/src/utils/vue-popper.js +198 -198
@@ -1,776 +1,776 @@
1
- <template>
2
- <div
3
- ref="reference"
4
- :class="[
5
- 'el-cascader',
6
- realSize && `el-cascader--${realSize}`,
7
- { 'is-disabled': isDisabled }
8
- ]"
9
- v-clickoutside="() => toggleDropDownVisible(false)"
10
- @mouseenter="inputHover = true"
11
- @mouseleave="inputHover = false"
12
- @click="() => toggleDropDownVisible(readonly ? undefined : true)"
13
- @keydown="handleKeyDown">
14
-
15
- <el-input
16
- ref="input"
17
- v-model="multiple ? presentText : inputValue"
18
- :size="realSize"
19
- :placeholder="placeholder"
20
- :readonly="readonly"
21
- :disabled="isDisabled"
22
- :validate-event="false"
23
- :class="{ 'is-focus': dropDownVisible }"
24
- @focus="handleFocus"
25
- @blur="handleBlur"
26
- @input="handleInput">
27
- <template slot="prefixLabel" v-if="$slots.prefixLabel">
28
- <slot name="prefixLabel"></slot>
29
- </template>
30
- <template slot="prefix" v-if="$slots.prefix">
31
- <slot name="prefix"></slot>
32
- </template>
33
- <template slot="suffix">
34
- <i
35
- v-if="clearBtnVisible"
36
- style="padding-right: 0;"
37
- key="clear"
38
- class="el-input__icon iov-icon-close-mini el-input__clear"
39
- @click.stop="handleClear"></i>
40
- <i
41
- v-else
42
- key="arrow-down"
43
- :class="[
44
- 'el-input__icon',
45
- 'iov-icon-arrow-up',
46
- dropDownVisible && 'is-reverse'
47
- ]"
48
- @click.stop="toggleDropDownVisible()"></i>
49
- </template>
50
- </el-input>
51
-
52
- <transition-group v-if="multiple && collapseTags && checkedNodes.length" class="el-cascader__tags" @after-leave="updateStyle">
53
- <template v-for="(tag, index) in presentTags">
54
- <el-tag
55
- :key="tag.key"
56
- v-if="collapseTags && index <= multipleLimitShow - 1"
57
- type="info"
58
- :size="tagSize"
59
- :hit="tag.hitState"
60
- :maxWidth="maxWidth"
61
- :closable="tag.closable"
62
- :class="{'is-disabled': !tag.closable && tag.key !== -1}"
63
- disable-transitions
64
- @close="deleteTag(tag)">
65
- <span>{{ tag.text }}</span>
66
- </el-tag>
67
- </template>
68
- <el-tag
69
- v-if="collapseTags && (checkedNodes.length > 1 && checkedNodes.length > multipleLimitShow || checkedNodes.length > 0 && collapseTagsFixed)"
70
- :closable="false"
71
- :size="tagSize"
72
- key="count"
73
- type="info"
74
- ref="tagsCount"
75
- class="el-cascader__tags-count"
76
- :class="{'el-cascader__tags-count-fixed': collapseTagsFixed}"
77
- disable-transitions>
78
- <span class="el-cascader__tags-text">{{collapseTagsFixed ? '' : '+'}}{{ collapseTagsFixed ? checkedNodes.length : checkedNodes.length - multipleLimitShow }}{{ collapseTagsSuffix }}</span>
79
- </el-tag>
80
- <input
81
- v-if="filterable && !isDisabled"
82
- v-model.trim="inputValue"
83
- type="text"
84
- class="el-cascader__search-input"
85
- :placeholder="presentTags.length ? '' : placeholder"
86
- @input="e => handleInput(inputValue, e)"
87
- @click.stop="toggleDropDownVisible(true)"
88
- @keydown.delete="handleDelete">
89
- </transition-group>
90
- <transition-group class="el-cascader__tags" @after-leave="updateStyle" v-if="!collapseTags">
91
- <template v-for="tag in presentTags">
92
- <el-tag
93
- :key="tag.key"
94
- type="info"
95
- :size="tagSize"
96
- :hit="tag.hitState"
97
- :maxWidth="maxWidth"
98
- :closable="tag.closable"
99
- :class="{'is-disabled': !tag.closable && tag.key !== -1}"
100
- disable-transitions
101
- @close="deleteTag(tag)">
102
- <span>{{ tag.text }}</span>
103
- </el-tag>
104
- </template>
105
- <input
106
- v-if="filterable && !isDisabled"
107
- v-model.trim="inputValue"
108
- type="text"
109
- class="el-cascader__search-input"
110
- :placeholder="presentTags.length ? '' : placeholder"
111
- @input="e => handleInput(inputValue, e)"
112
- @click.stop="toggleDropDownVisible(true)"
113
- @keydown.delete="handleDelete">
114
- </transition-group>
115
-
116
-
117
- <transition name="el-zoom-in-top" @after-leave="handleDropdownLeave">
118
- <div
119
- v-show="dropDownVisible"
120
- ref="popper"
121
- :class="['el-popper', 'el-cascader__dropdown', popperClass]">
122
- <el-cascader-panel
123
- ref="panel"
124
- v-show="!filtering"
125
- v-model="checkedValue"
126
- :options="options"
127
- :props="config"
128
- :border="false"
129
- :render-label="$scopedSlots.default"
130
- @expand-change="handleExpandChange"
131
- @close="toggleDropDownVisible(false)"></el-cascader-panel>
132
- <el-scrollbar
133
- ref="suggestionPanel"
134
- v-if="filterable"
135
- v-show="filtering"
136
- tag="ul"
137
- class="el-cascader__suggestion-panel"
138
- view-class="el-cascader__suggestion-list"
139
- @keydown.native="handleSuggestionKeyDown">
140
- <template v-if="suggestions.length">
141
- <li
142
- v-for="(item, index) in suggestions"
143
- :key="item.uid"
144
- :class="[
145
- 'el-cascader__suggestion-item',
146
- item.checked && 'is-checked'
147
- ]"
148
- :tabindex="-1"
149
- @click="handleSuggestionClick(index)">
150
- <span>{{ item.text }}</span>
151
- </li>
152
- </template>
153
- <slot v-else name="empty">
154
- <li class="el-cascader__empty-text">{{ t('el.cascader.noMatch') }}</li>
155
- </slot>
156
- </el-scrollbar>
157
- </div>
158
- </transition>
159
- </div>
160
- </template>
161
-
162
- <script>
163
- import Popper from 'iov-design/src/utils/vue-popper';
164
- import Clickoutside from 'iov-design/src/utils/clickoutside';
165
- import Emitter from 'iov-design/src/mixins/emitter';
166
- import Locale from 'iov-design/src/mixins/locale';
167
- import Migrating from 'iov-design/src/mixins/migrating';
168
- import ElInput from 'iov-design/packages/input';
169
- import ElTag from 'iov-design/packages/tag';
170
- import ElScrollbar from 'iov-design/packages/scrollbar';
171
- import ElCascaderPanel from 'iov-design/packages/cascader-panel';
172
- import AriaUtils from 'iov-design/src/utils/aria-utils';
173
- import { t } from 'iov-design/src/locale';
174
- import { isEqual, isEmpty, kebabCase } from 'iov-design/src/utils/util';
175
- import { isUndefined, isFunction } from 'iov-design/src/utils/types';
176
- import { isDef } from 'iov-design/src/utils/shared';
177
- import { addResizeListener, removeResizeListener } from 'iov-design/src/utils/resize-event';
178
- import debounce from 'throttle-debounce/debounce';
179
-
180
- const { keys: KeyCode } = AriaUtils;
181
- const MigratingProps = {
182
- expandTrigger: {
183
- newProp: 'expandTrigger',
184
- type: String
185
- },
186
- changeOnSelect: {
187
- newProp: 'checkStrictly',
188
- type: Boolean
189
- },
190
- hoverThreshold: {
191
- newProp: 'hoverThreshold',
192
- type: Number
193
- }
194
- };
195
-
196
- const PopperMixin = {
197
- props: {
198
- placement: {
199
- type: String,
200
- default: 'bottom-start'
201
- },
202
- appendToBody: Popper.props.appendToBody,
203
- visibleArrow: {
204
- type: Boolean,
205
- default: true
206
- },
207
- arrowOffset: Popper.props.arrowOffset,
208
- offset: Popper.props.offset,
209
- boundariesPadding: Popper.props.boundariesPadding,
210
- popperOptions: Popper.props.popperOptions,
211
- transformOrigin: Popper.props.transformOrigin
212
- },
213
- methods: Popper.methods,
214
- data: Popper.data,
215
- beforeDestroy: Popper.beforeDestroy
216
- };
217
-
218
- const InputSizeMap = {
219
- medium: 32,
220
- small: 30,
221
- mini: 26
222
- };
223
-
224
- export default {
225
- name: 'ElCascader',
226
-
227
- directives: { Clickoutside },
228
-
229
- mixins: [PopperMixin, Emitter, Locale, Migrating],
230
-
231
- inject: {
232
- elForm: {
233
- default: ''
234
- },
235
- elFormItem: {
236
- default: ''
237
- }
238
- },
239
-
240
- components: {
241
- ElInput,
242
- ElTag,
243
- ElScrollbar,
244
- ElCascaderPanel
245
- },
246
-
247
- props: {
248
- value: {},
249
- options: Array,
250
- props: Object,
251
- size: String,
252
- placeholder: {
253
- type: String,
254
- default: () => t('el.cascader.placeholder')
255
- },
256
- disabled: Boolean,
257
- clearable: Boolean,
258
- filterable: Boolean,
259
- filterMethod: Function,
260
- separator: {
261
- type: String,
262
- default: ' / '
263
- },
264
- showAllLevels: {
265
- type: Boolean,
266
- default: true
267
- },
268
- collapseTags: Boolean,
269
- multipleLimitShow: {
270
- type: Number,
271
- default: 1
272
- },
273
- multipleTagMaxWidth: {
274
- type: String,
275
- default: 'none'
276
- },
277
- collapseTagsSuffix: {
278
- type: String,
279
- default: ''
280
- },
281
- collapseTagsFixed: {
282
- type: Boolean,
283
- default: false
284
- },
285
- debounce: {
286
- type: Number,
287
- default: 300
288
- },
289
- beforeFilter: {
290
- type: Function,
291
- default: () => (() => {})
292
- },
293
- popperClass: String
294
- },
295
-
296
- data() {
297
- return {
298
- dropDownVisible: false,
299
- checkedValue: this.value,
300
- inputHover: false,
301
- inputValue: null,
302
- presentText: null,
303
- presentTags: [],
304
- checkedNodes: [],
305
- filtering: false,
306
- suggestions: [],
307
- inputInitialHeight: 0,
308
- pressDeleteCount: 0,
309
- inputWidth: 0,
310
- tagsLeft: 0,
311
- maxWidth: 'none'
312
- };
313
- },
314
-
315
- computed: {
316
- realSize() {
317
- const _elFormItemSize = (this.elFormItem || {}).elFormItemSize;
318
- return this.size || _elFormItemSize || (this.$ELEMENT || {}).size;
319
- },
320
- tagSize() {
321
- return this.realSize;
322
- // return ['small', 'mini'].indexOf(this.realSize) > -1
323
- // ? 'mini'
324
- // : 'small';
325
- },
326
- isDisabled() {
327
- return this.disabled || (this.elForm || {}).disabled;
328
- },
329
- config() {
330
- const config = this.props || {};
331
- const { $attrs } = this;
332
-
333
- Object
334
- .keys(MigratingProps)
335
- .forEach(oldProp => {
336
- const { newProp, type } = MigratingProps[oldProp];
337
- let oldValue = $attrs[oldProp] || $attrs[kebabCase(oldProp)];
338
- if (isDef(oldProp) && !isDef(config[newProp])) {
339
- if (type === Boolean && oldValue === '') {
340
- oldValue = true;
341
- }
342
- config[newProp] = oldValue;
343
- }
344
- });
345
-
346
- return config;
347
- },
348
- multiple() {
349
- return this.config.multiple;
350
- },
351
- leafOnly() {
352
- return !this.config.checkStrictly;
353
- },
354
- readonly() {
355
- return !this.filterable || this.multiple;
356
- },
357
- clearBtnVisible() {
358
- if (!this.clearable || this.isDisabled || this.filtering || !this.inputHover) {
359
- return false;
360
- }
361
-
362
- return this.multiple
363
- ? !!this.checkedNodes.filter(node => !node.isDisabled).length
364
- : !!this.presentText;
365
- },
366
- panel() {
367
- return this.$refs.panel;
368
- }
369
- },
370
-
371
- watch: {
372
- disabled() {
373
- this.computePresentContent();
374
- },
375
- value(val) {
376
- if (!isEqual(val, this.checkedValue)) {
377
- this.checkedValue = val;
378
- this.computePresentContent();
379
- }
380
- },
381
- checkedValue(val) {
382
- const { value, dropDownVisible } = this;
383
- const { checkStrictly, multiple } = this.config;
384
-
385
- if (!isEqual(val, value) || isUndefined(value)) {
386
- this.computePresentContent();
387
- // hide dropdown when single mode
388
- if (!multiple && !checkStrictly && dropDownVisible) {
389
- this.toggleDropDownVisible(false);
390
- }
391
-
392
- this.$emit('input', val);
393
- this.$emit('change', val);
394
- this.dispatch('ElFormItem', 'el.form.change', [val]);
395
- }
396
- },
397
- options: {
398
- handler: function() {
399
- this.$nextTick(this.computePresentContent);
400
- },
401
- deep: true
402
- },
403
- presentText(val) {
404
- this.inputValue = val;
405
- },
406
- presentTags(val, oldVal) {
407
- if (this.multiple && (val.length || oldVal.length)) {
408
- this.$nextTick(this.updateStyle);
409
- }
410
- },
411
- filtering(val) {
412
- this.$nextTick(this.updatePopper);
413
- }
414
- },
415
-
416
- mounted() {
417
- const { input } = this.$refs;
418
- if (input && input.$el) {
419
- this.inputInitialHeight = Math.max(input.$el.offsetHeight, InputSizeMap[this.realSize]) || 36;
420
- this.resetInputWidth();
421
- this.resetTagsLeft();
422
- }
423
-
424
- if (!this.isEmptyValue(this.value)) {
425
- this.computePresentContent();
426
- }
427
-
428
- this.filterHandler = debounce(this.debounce, () => {
429
- const { inputValue } = this;
430
-
431
- if (!inputValue) {
432
- this.filtering = false;
433
- return;
434
- }
435
-
436
- const before = this.beforeFilter(inputValue);
437
- if (before && before.then) {
438
- before.then(this.getSuggestions);
439
- } else if (before !== false) {
440
- this.getSuggestions();
441
- } else {
442
- this.filtering = false;
443
- }
444
- });
445
-
446
- addResizeListener(this.$el, this.updateStyle);
447
- },
448
-
449
- beforeDestroy() {
450
- removeResizeListener(this.$el, this.updateStyle);
451
- },
452
-
453
- methods: {
454
- resetInputWidth() {
455
- this.inputWidth = this.$refs.input.$el.getBoundingClientRect().width;
456
- },
457
- resetTagsLeft() {
458
- this.$nextTick(() => {
459
- const prefixLabel = this.$el.querySelector('.el-input-group__prefix-label');
460
- const prefix = this.$el.querySelector('.el-input__prefix');
461
- const inputInner = this.$el.querySelector('.el-input__inner');
462
- const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
463
- const inputPaddingLeft = prefixLabel || prefix ? Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) : 0;
464
- this.tagsLeft = prefixLabelWidth + inputPaddingLeft;
465
- });
466
- },
467
- getMaxWidth() {
468
- this.$nextTick(() => {
469
- if (this.collapseTags) {
470
- if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
471
- this.maxWidth = this.multipleTagMaxWidth;
472
- }
473
- const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
474
- const count = this.checkedNodes.length <= this.multipleLimitShow ? this.checkedNodes.length : this.multipleLimitShow;
475
- this.maxWidth = Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
476
- } else {
477
- this.maxWidth = this.multipleTagMaxWidth || 'none';
478
- }
479
- });
480
- },
481
- getMigratingConfig() {
482
- return {
483
- props: {
484
- 'expand-trigger': 'expand-trigger is removed, use `props.expandTrigger` instead.',
485
- 'change-on-select': 'change-on-select is removed, use `props.checkStrictly` instead.',
486
- 'hover-threshold': 'hover-threshold is removed, use `props.hoverThreshold` instead'
487
- },
488
- events: {
489
- 'active-item-change': 'active-item-change is renamed to expand-change'
490
- }
491
- };
492
- },
493
- toggleDropDownVisible(visible) {
494
- if (this.isDisabled) return;
495
-
496
- const { dropDownVisible } = this;
497
- const { input } = this.$refs;
498
- visible = isDef(visible) ? visible : !dropDownVisible;
499
- if (visible !== dropDownVisible) {
500
- this.dropDownVisible = visible;
501
- if (visible) {
502
- this.$nextTick(() => {
503
- this.updatePopper();
504
- this.panel.scrollIntoView();
505
- });
506
- }
507
- input.$refs.input.setAttribute('aria-expanded', visible);
508
- this.$emit('visible-change', visible);
509
- }
510
- },
511
- handleDropdownLeave() {
512
- this.filtering = false;
513
- this.inputValue = this.presentText;
514
- this.doDestroy();
515
- },
516
- handleKeyDown(event) {
517
- switch (event.keyCode) {
518
- case KeyCode.enter:
519
- this.toggleDropDownVisible();
520
- break;
521
- case KeyCode.down:
522
- this.toggleDropDownVisible(true);
523
- this.focusFirstNode();
524
- event.preventDefault();
525
- break;
526
- case KeyCode.esc:
527
- case KeyCode.tab:
528
- this.toggleDropDownVisible(false);
529
- break;
530
- }
531
- },
532
- handleFocus(e) {
533
- this.$emit('focus', e);
534
- },
535
- handleBlur(e) {
536
- this.$emit('blur', e);
537
- },
538
- handleInput(val, event) {
539
- !this.dropDownVisible && this.toggleDropDownVisible(true);
540
-
541
- if (event && event.isComposing) return;
542
- if (val) {
543
- this.filterHandler();
544
- } else {
545
- this.filtering = false;
546
- }
547
- },
548
- handleClear() {
549
- this.presentText = '';
550
- this.panel.clearCheckedNodes();
551
- },
552
- handleExpandChange(value) {
553
- this.$nextTick(this.updatePopper.bind(this));
554
- this.$emit('expand-change', value);
555
- this.$emit('active-item-change', value); // Deprecated
556
- },
557
- focusFirstNode() {
558
- this.$nextTick(() => {
559
- const { filtering } = this;
560
- const { popper, suggestionPanel } = this.$refs;
561
- let firstNode = null;
562
-
563
- if (filtering && suggestionPanel) {
564
- firstNode = suggestionPanel.$el.querySelector('.el-cascader__suggestion-item');
565
- } else {
566
- const firstMenu = popper.querySelector('.el-cascader-menu');
567
- firstNode = firstMenu.querySelector('.el-cascader-node[tabindex="-1"]');
568
- }
569
-
570
- if (firstNode) {
571
- firstNode.focus();
572
- !filtering && firstNode.click();
573
- }
574
- });
575
- },
576
- computePresentContent() {
577
- // nextTick is required, because checked nodes may not change right now
578
- this.$nextTick(() => {
579
- if (this.config.multiple) {
580
- this.computePresentTags();
581
- this.presentText = this.presentTags.length ? ' ' : null;
582
- } else {
583
- this.computePresentText();
584
- }
585
- });
586
- },
587
- isEmptyValue(val) {
588
- const { multiple } = this;
589
- const { emitPath } = this.panel.config;
590
- if (multiple || emitPath) {
591
- return isEmpty(val);
592
- }
593
- return false;
594
- },
595
- computePresentText() {
596
- const { checkedValue, config } = this;
597
- if (!this.isEmptyValue(checkedValue)) {
598
- const node = this.panel.getNodeByValue(checkedValue);
599
- if (node && (config.checkStrictly || node.isLeaf)) {
600
- this.presentText = node.getText(this.showAllLevels, this.separator);
601
- return;
602
- }
603
- }
604
- this.presentText = null;
605
- },
606
- computePresentTags() {
607
- const { isDisabled, leafOnly, showAllLevels, separator } = this;
608
- const checkedNodes = this.getCheckedNodes(leafOnly);
609
- const tags = [];
610
-
611
- const genTag = node => ({
612
- node,
613
- key: node.uid,
614
- text: node.getText(showAllLevels, separator),
615
- hitState: false,
616
- closable: !isDisabled && !node.isDisabled
617
- });
618
-
619
- if (checkedNodes.length) {
620
- checkedNodes.forEach(node => tags.push(genTag(node)));
621
- // const [first, ...rest] = checkedNodes;
622
- // const restCount = rest.length;
623
- // tags.push(genTag(first));
624
-
625
- // console.log(restCount, 'restCount============');
626
- // this.restCount = restCount;
627
- // if (restCount) {
628
- // if (collapseTags) {
629
- // tags.push({
630
- // key: -1,
631
- // text: `+${restCount}`,
632
- // closable: false
633
- // });
634
- // } else {
635
- // rest.forEach(node => tags.push(genTag(node)));
636
- // }
637
- // }
638
- }
639
-
640
- this.checkedNodes = checkedNodes;
641
- this.presentTags = tags;
642
- this.getMaxWidth();
643
- },
644
- getSuggestions() {
645
- let { filterMethod } = this;
646
-
647
- if (!isFunction(filterMethod)) {
648
- filterMethod = (node, keyword) => node.text.includes(keyword);
649
- }
650
-
651
- const suggestions = this.panel.getFlattedNodes(this.leafOnly)
652
- .filter(node => {
653
- if (node.isDisabled) return false;
654
- node.text = node.getText(this.showAllLevels, this.separator) || '';
655
- return filterMethod(node, this.inputValue);
656
- });
657
-
658
- if (this.multiple) {
659
- this.presentTags.forEach(tag => {
660
- tag.hitState = false;
661
- });
662
- } else {
663
- suggestions.forEach(node => {
664
- node.checked = isEqual(this.checkedValue, node.getValueByOption());
665
- });
666
- }
667
-
668
- this.filtering = true;
669
- this.suggestions = suggestions;
670
- this.$nextTick(this.updatePopper);
671
- },
672
- handleSuggestionKeyDown(event) {
673
- const { keyCode, target } = event;
674
- switch (keyCode) {
675
- case KeyCode.enter:
676
- target.click();
677
- break;
678
- case KeyCode.up:
679
- const prev = target.previousElementSibling;
680
- prev && prev.focus();
681
- break;
682
- case KeyCode.down:
683
- const next = target.nextElementSibling;
684
- next && next.focus();
685
- break;
686
- case KeyCode.esc:
687
- case KeyCode.tab:
688
- this.toggleDropDownVisible(false);
689
- break;
690
- }
691
- },
692
- handleDelete() {
693
- const { inputValue, pressDeleteCount, presentTags } = this;
694
- const lastIndex = presentTags.length - 1;
695
- const lastTag = presentTags[lastIndex];
696
- this.pressDeleteCount = inputValue ? 0 : pressDeleteCount + 1;
697
-
698
- if (!lastTag) return;
699
-
700
- if (this.pressDeleteCount) {
701
- if (lastTag.hitState) {
702
- this.deleteTag(lastTag);
703
- } else {
704
- lastTag.hitState = true;
705
- }
706
- }
707
- },
708
- handleSuggestionClick(index) {
709
- const { multiple } = this;
710
- const targetNode = this.suggestions[index];
711
-
712
- if (multiple) {
713
- const { checked } = targetNode;
714
- targetNode.doCheck(!checked);
715
- this.panel.calculateMultiCheckedValue();
716
- } else {
717
- this.checkedValue = targetNode.getValueByOption();
718
- this.toggleDropDownVisible(false);
719
- }
720
- },
721
- deleteTag(tag) {
722
- const { checkedValue } = this;
723
- const current = tag.node.getValueByOption();
724
- const val = checkedValue.find(n => isEqual(n, current));
725
- this.checkedValue = checkedValue.filter(n => !isEqual(n, current));
726
- this.$emit('remove-tag', val);
727
- },
728
- updateStyle() {
729
- const { $el, inputInitialHeight } = this;
730
- if (this.$isServer || !$el) return;
731
-
732
- const { suggestionPanel } = this.$refs;
733
- const inputInner = $el.querySelector('.el-input__inner');
734
-
735
- if (!inputInner) return;
736
-
737
- const tags = $el.querySelector('.el-cascader__tags');
738
- const groupPrefix = $el.querySelector('.el-input-group--prefix');
739
- const prefixLabel = $el.querySelector('.el-input-group__prefix-label');
740
- let suggestionPanelEl = null;
741
-
742
- if (suggestionPanel && (suggestionPanelEl = suggestionPanel.$el)) {
743
- const suggestionList = suggestionPanelEl.querySelector('.el-cascader__suggestion-list');
744
- suggestionList.style.minWidth = inputInner.offsetWidth + 'px';
745
- }
746
-
747
- if (tags) {
748
- const offsetHeight = Math.round(tags.getBoundingClientRect().height);
749
- const height = Math.max(offsetHeight + 4, inputInitialHeight) + 'px';
750
- const inputPaddingLeft = Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) || 0;
751
- const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
752
- if (groupPrefix) {
753
- groupPrefix.style.height = height;
754
- } else {
755
- inputInner.style.height = height;
756
- }
757
- tags.style.left = prefixLabel ? (prefixLabelWidth + inputPaddingLeft - 4) + 'px' : '0px';
758
- if (this.checkedNodes.length === 0 && !prefixLabel) {
759
- tags.style.left = '12px';
760
- }
761
- if (this.dropDownVisible) {
762
- this.updatePopper();
763
- }
764
- }
765
- },
766
-
767
- /**
768
- * public methods
769
- */
770
- getCheckedNodes(leafOnly) {
771
- return this.panel.getCheckedNodes(leafOnly);
772
- }
773
- }
774
- };
775
- </script>
776
-
1
+ <template>
2
+ <div
3
+ ref="reference"
4
+ :class="[
5
+ 'el-cascader',
6
+ realSize && `el-cascader--${realSize}`,
7
+ { 'is-disabled': isDisabled }
8
+ ]"
9
+ v-clickoutside="() => toggleDropDownVisible(false)"
10
+ @mouseenter="inputHover = true"
11
+ @mouseleave="inputHover = false"
12
+ @click="() => toggleDropDownVisible(readonly ? undefined : true)"
13
+ @keydown="handleKeyDown">
14
+
15
+ <el-input
16
+ ref="input"
17
+ v-model="multiple ? presentText : inputValue"
18
+ :size="realSize"
19
+ :placeholder="placeholder"
20
+ :readonly="readonly"
21
+ :disabled="isDisabled"
22
+ :validate-event="false"
23
+ :class="{ 'is-focus': dropDownVisible }"
24
+ @focus="handleFocus"
25
+ @blur="handleBlur"
26
+ @input="handleInput">
27
+ <template slot="prefixLabel" v-if="$slots.prefixLabel">
28
+ <slot name="prefixLabel"></slot>
29
+ </template>
30
+ <template slot="prefix" v-if="$slots.prefix">
31
+ <slot name="prefix"></slot>
32
+ </template>
33
+ <template slot="suffix">
34
+ <i
35
+ v-if="clearBtnVisible"
36
+ style="padding-right: 0;"
37
+ key="clear"
38
+ class="el-input__icon iov-icon-close-mini el-input__clear"
39
+ @click.stop="handleClear"></i>
40
+ <i
41
+ v-else
42
+ key="arrow-down"
43
+ :class="[
44
+ 'el-input__icon',
45
+ 'iov-icon-arrow-up',
46
+ dropDownVisible && 'is-reverse'
47
+ ]"
48
+ @click.stop="toggleDropDownVisible()"></i>
49
+ </template>
50
+ </el-input>
51
+
52
+ <transition-group v-if="multiple && collapseTags && checkedNodes.length" class="el-cascader__tags" @after-leave="updateStyle">
53
+ <template v-for="(tag, index) in presentTags">
54
+ <el-tag
55
+ :key="tag.key"
56
+ v-if="collapseTags && index <= multipleLimitShow - 1"
57
+ type="info"
58
+ :size="tagSize"
59
+ :hit="tag.hitState"
60
+ :maxWidth="maxWidth"
61
+ :closable="tag.closable"
62
+ :class="{'is-disabled': !tag.closable && tag.key !== -1}"
63
+ disable-transitions
64
+ @close="deleteTag(tag)">
65
+ <span>{{ tag.text }}</span>
66
+ </el-tag>
67
+ </template>
68
+ <el-tag
69
+ v-if="collapseTags && (checkedNodes.length > 1 && checkedNodes.length > multipleLimitShow || checkedNodes.length > 0 && collapseTagsFixed)"
70
+ :closable="false"
71
+ :size="tagSize"
72
+ key="count"
73
+ type="info"
74
+ ref="tagsCount"
75
+ class="el-cascader__tags-count"
76
+ :class="{'el-cascader__tags-count-fixed': collapseTagsFixed}"
77
+ disable-transitions>
78
+ <span class="el-cascader__tags-text">{{collapseTagsFixed ? '' : '+'}}{{ collapseTagsFixed ? checkedNodes.length : checkedNodes.length - multipleLimitShow }}{{ collapseTagsSuffix }}</span>
79
+ </el-tag>
80
+ <input
81
+ v-if="filterable && !isDisabled"
82
+ v-model.trim="inputValue"
83
+ type="text"
84
+ class="el-cascader__search-input"
85
+ :placeholder="presentTags.length ? '' : placeholder"
86
+ @input="e => handleInput(inputValue, e)"
87
+ @click.stop="toggleDropDownVisible(true)"
88
+ @keydown.delete="handleDelete">
89
+ </transition-group>
90
+ <transition-group class="el-cascader__tags" @after-leave="updateStyle" v-if="!collapseTags">
91
+ <template v-for="tag in presentTags">
92
+ <el-tag
93
+ :key="tag.key"
94
+ type="info"
95
+ :size="tagSize"
96
+ :hit="tag.hitState"
97
+ :maxWidth="maxWidth"
98
+ :closable="tag.closable"
99
+ :class="{'is-disabled': !tag.closable && tag.key !== -1}"
100
+ disable-transitions
101
+ @close="deleteTag(tag)">
102
+ <span>{{ tag.text }}</span>
103
+ </el-tag>
104
+ </template>
105
+ <input
106
+ v-if="filterable && !isDisabled"
107
+ v-model.trim="inputValue"
108
+ type="text"
109
+ class="el-cascader__search-input"
110
+ :placeholder="presentTags.length ? '' : placeholder"
111
+ @input="e => handleInput(inputValue, e)"
112
+ @click.stop="toggleDropDownVisible(true)"
113
+ @keydown.delete="handleDelete">
114
+ </transition-group>
115
+
116
+
117
+ <transition name="el-zoom-in-top" @after-leave="handleDropdownLeave">
118
+ <div
119
+ v-show="dropDownVisible"
120
+ ref="popper"
121
+ :class="['el-popper', 'el-cascader__dropdown', popperClass]">
122
+ <el-cascader-panel
123
+ ref="panel"
124
+ v-show="!filtering"
125
+ v-model="checkedValue"
126
+ :options="options"
127
+ :props="config"
128
+ :border="false"
129
+ :render-label="$scopedSlots.default"
130
+ @expand-change="handleExpandChange"
131
+ @close="toggleDropDownVisible(false)"></el-cascader-panel>
132
+ <el-scrollbar
133
+ ref="suggestionPanel"
134
+ v-if="filterable"
135
+ v-show="filtering"
136
+ tag="ul"
137
+ class="el-cascader__suggestion-panel"
138
+ view-class="el-cascader__suggestion-list"
139
+ @keydown.native="handleSuggestionKeyDown">
140
+ <template v-if="suggestions.length">
141
+ <li
142
+ v-for="(item, index) in suggestions"
143
+ :key="item.uid"
144
+ :class="[
145
+ 'el-cascader__suggestion-item',
146
+ item.checked && 'is-checked'
147
+ ]"
148
+ :tabindex="-1"
149
+ @click="handleSuggestionClick(index)">
150
+ <span>{{ item.text }}</span>
151
+ </li>
152
+ </template>
153
+ <slot v-else name="empty">
154
+ <li class="el-cascader__empty-text">{{ t('el.cascader.noMatch') }}</li>
155
+ </slot>
156
+ </el-scrollbar>
157
+ </div>
158
+ </transition>
159
+ </div>
160
+ </template>
161
+
162
+ <script>
163
+ import Popper from 'iov-design/src/utils/vue-popper';
164
+ import Clickoutside from 'iov-design/src/utils/clickoutside';
165
+ import Emitter from 'iov-design/src/mixins/emitter';
166
+ import Locale from 'iov-design/src/mixins/locale';
167
+ import Migrating from 'iov-design/src/mixins/migrating';
168
+ import ElInput from 'iov-design/packages/input';
169
+ import ElTag from 'iov-design/packages/tag';
170
+ import ElScrollbar from 'iov-design/packages/scrollbar';
171
+ import ElCascaderPanel from 'iov-design/packages/cascader-panel';
172
+ import AriaUtils from 'iov-design/src/utils/aria-utils';
173
+ import { t } from 'iov-design/src/locale';
174
+ import { isEqual, isEmpty, kebabCase } from 'iov-design/src/utils/util';
175
+ import { isUndefined, isFunction } from 'iov-design/src/utils/types';
176
+ import { isDef } from 'iov-design/src/utils/shared';
177
+ import { addResizeListener, removeResizeListener } from 'iov-design/src/utils/resize-event';
178
+ import debounce from 'throttle-debounce/debounce';
179
+
180
+ const { keys: KeyCode } = AriaUtils;
181
+ const MigratingProps = {
182
+ expandTrigger: {
183
+ newProp: 'expandTrigger',
184
+ type: String
185
+ },
186
+ changeOnSelect: {
187
+ newProp: 'checkStrictly',
188
+ type: Boolean
189
+ },
190
+ hoverThreshold: {
191
+ newProp: 'hoverThreshold',
192
+ type: Number
193
+ }
194
+ };
195
+
196
+ const PopperMixin = {
197
+ props: {
198
+ placement: {
199
+ type: String,
200
+ default: 'bottom-start'
201
+ },
202
+ appendToBody: Popper.props.appendToBody,
203
+ visibleArrow: {
204
+ type: Boolean,
205
+ default: true
206
+ },
207
+ arrowOffset: Popper.props.arrowOffset,
208
+ offset: Popper.props.offset,
209
+ boundariesPadding: Popper.props.boundariesPadding,
210
+ popperOptions: Popper.props.popperOptions,
211
+ transformOrigin: Popper.props.transformOrigin
212
+ },
213
+ methods: Popper.methods,
214
+ data: Popper.data,
215
+ beforeDestroy: Popper.beforeDestroy
216
+ };
217
+
218
+ const InputSizeMap = {
219
+ medium: 32,
220
+ small: 30,
221
+ mini: 26
222
+ };
223
+
224
+ export default {
225
+ name: 'ElCascader',
226
+
227
+ directives: { Clickoutside },
228
+
229
+ mixins: [PopperMixin, Emitter, Locale, Migrating],
230
+
231
+ inject: {
232
+ elForm: {
233
+ default: ''
234
+ },
235
+ elFormItem: {
236
+ default: ''
237
+ }
238
+ },
239
+
240
+ components: {
241
+ ElInput,
242
+ ElTag,
243
+ ElScrollbar,
244
+ ElCascaderPanel
245
+ },
246
+
247
+ props: {
248
+ value: {},
249
+ options: Array,
250
+ props: Object,
251
+ size: String,
252
+ placeholder: {
253
+ type: String,
254
+ default: () => t('el.cascader.placeholder')
255
+ },
256
+ disabled: Boolean,
257
+ clearable: Boolean,
258
+ filterable: Boolean,
259
+ filterMethod: Function,
260
+ separator: {
261
+ type: String,
262
+ default: ' / '
263
+ },
264
+ showAllLevels: {
265
+ type: Boolean,
266
+ default: true
267
+ },
268
+ collapseTags: Boolean,
269
+ multipleLimitShow: {
270
+ type: Number,
271
+ default: 1
272
+ },
273
+ multipleTagMaxWidth: {
274
+ type: String,
275
+ default: 'none'
276
+ },
277
+ collapseTagsSuffix: {
278
+ type: String,
279
+ default: ''
280
+ },
281
+ collapseTagsFixed: {
282
+ type: Boolean,
283
+ default: false
284
+ },
285
+ debounce: {
286
+ type: Number,
287
+ default: 300
288
+ },
289
+ beforeFilter: {
290
+ type: Function,
291
+ default: () => (() => {})
292
+ },
293
+ popperClass: String
294
+ },
295
+
296
+ data() {
297
+ return {
298
+ dropDownVisible: false,
299
+ checkedValue: this.value,
300
+ inputHover: false,
301
+ inputValue: null,
302
+ presentText: null,
303
+ presentTags: [],
304
+ checkedNodes: [],
305
+ filtering: false,
306
+ suggestions: [],
307
+ inputInitialHeight: 0,
308
+ pressDeleteCount: 0,
309
+ inputWidth: 0,
310
+ tagsLeft: 0,
311
+ maxWidth: 'none'
312
+ };
313
+ },
314
+
315
+ computed: {
316
+ realSize() {
317
+ const _elFormItemSize = (this.elFormItem || {}).elFormItemSize;
318
+ return this.size || _elFormItemSize || (this.$ELEMENT || {}).size;
319
+ },
320
+ tagSize() {
321
+ return this.realSize;
322
+ // return ['small', 'mini'].indexOf(this.realSize) > -1
323
+ // ? 'mini'
324
+ // : 'small';
325
+ },
326
+ isDisabled() {
327
+ return this.disabled || (this.elForm || {}).disabled;
328
+ },
329
+ config() {
330
+ const config = this.props || {};
331
+ const { $attrs } = this;
332
+
333
+ Object
334
+ .keys(MigratingProps)
335
+ .forEach(oldProp => {
336
+ const { newProp, type } = MigratingProps[oldProp];
337
+ let oldValue = $attrs[oldProp] || $attrs[kebabCase(oldProp)];
338
+ if (isDef(oldProp) && !isDef(config[newProp])) {
339
+ if (type === Boolean && oldValue === '') {
340
+ oldValue = true;
341
+ }
342
+ config[newProp] = oldValue;
343
+ }
344
+ });
345
+
346
+ return config;
347
+ },
348
+ multiple() {
349
+ return this.config.multiple;
350
+ },
351
+ leafOnly() {
352
+ return !this.config.checkStrictly;
353
+ },
354
+ readonly() {
355
+ return !this.filterable || this.multiple;
356
+ },
357
+ clearBtnVisible() {
358
+ if (!this.clearable || this.isDisabled || this.filtering || !this.inputHover) {
359
+ return false;
360
+ }
361
+
362
+ return this.multiple
363
+ ? !!this.checkedNodes.filter(node => !node.isDisabled).length
364
+ : !!this.presentText;
365
+ },
366
+ panel() {
367
+ return this.$refs.panel;
368
+ }
369
+ },
370
+
371
+ watch: {
372
+ disabled() {
373
+ this.computePresentContent();
374
+ },
375
+ value(val) {
376
+ if (!isEqual(val, this.checkedValue)) {
377
+ this.checkedValue = val;
378
+ this.computePresentContent();
379
+ }
380
+ },
381
+ checkedValue(val) {
382
+ const { value, dropDownVisible } = this;
383
+ const { checkStrictly, multiple } = this.config;
384
+
385
+ if (!isEqual(val, value) || isUndefined(value)) {
386
+ this.computePresentContent();
387
+ // hide dropdown when single mode
388
+ if (!multiple && !checkStrictly && dropDownVisible) {
389
+ this.toggleDropDownVisible(false);
390
+ }
391
+
392
+ this.$emit('input', val);
393
+ this.$emit('change', val);
394
+ this.dispatch('ElFormItem', 'el.form.change', [val]);
395
+ }
396
+ },
397
+ options: {
398
+ handler: function() {
399
+ this.$nextTick(this.computePresentContent);
400
+ },
401
+ deep: true
402
+ },
403
+ presentText(val) {
404
+ this.inputValue = val;
405
+ },
406
+ presentTags(val, oldVal) {
407
+ if (this.multiple && (val.length || oldVal.length)) {
408
+ this.$nextTick(this.updateStyle);
409
+ }
410
+ },
411
+ filtering(val) {
412
+ this.$nextTick(this.updatePopper);
413
+ }
414
+ },
415
+
416
+ mounted() {
417
+ const { input } = this.$refs;
418
+ if (input && input.$el) {
419
+ this.inputInitialHeight = Math.max(input.$el.offsetHeight, InputSizeMap[this.realSize]) || 36;
420
+ this.resetInputWidth();
421
+ this.resetTagsLeft();
422
+ }
423
+
424
+ if (!this.isEmptyValue(this.value)) {
425
+ this.computePresentContent();
426
+ }
427
+
428
+ this.filterHandler = debounce(this.debounce, () => {
429
+ const { inputValue } = this;
430
+
431
+ if (!inputValue) {
432
+ this.filtering = false;
433
+ return;
434
+ }
435
+
436
+ const before = this.beforeFilter(inputValue);
437
+ if (before && before.then) {
438
+ before.then(this.getSuggestions);
439
+ } else if (before !== false) {
440
+ this.getSuggestions();
441
+ } else {
442
+ this.filtering = false;
443
+ }
444
+ });
445
+
446
+ addResizeListener(this.$el, this.updateStyle);
447
+ },
448
+
449
+ beforeDestroy() {
450
+ removeResizeListener(this.$el, this.updateStyle);
451
+ },
452
+
453
+ methods: {
454
+ resetInputWidth() {
455
+ this.inputWidth = this.$refs.input.$el.getBoundingClientRect().width;
456
+ },
457
+ resetTagsLeft() {
458
+ this.$nextTick(() => {
459
+ const prefixLabel = this.$el.querySelector('.el-input-group__prefix-label');
460
+ const prefix = this.$el.querySelector('.el-input__prefix');
461
+ const inputInner = this.$el.querySelector('.el-input__inner');
462
+ const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
463
+ const inputPaddingLeft = prefixLabel || prefix ? Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) : 0;
464
+ this.tagsLeft = prefixLabelWidth + inputPaddingLeft;
465
+ });
466
+ },
467
+ getMaxWidth() {
468
+ this.$nextTick(() => {
469
+ if (this.collapseTags) {
470
+ if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
471
+ this.maxWidth = this.multipleTagMaxWidth;
472
+ }
473
+ const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
474
+ const count = this.checkedNodes.length <= this.multipleLimitShow ? this.checkedNodes.length : this.multipleLimitShow;
475
+ this.maxWidth = Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
476
+ } else {
477
+ this.maxWidth = this.multipleTagMaxWidth || 'none';
478
+ }
479
+ });
480
+ },
481
+ getMigratingConfig() {
482
+ return {
483
+ props: {
484
+ 'expand-trigger': 'expand-trigger is removed, use `props.expandTrigger` instead.',
485
+ 'change-on-select': 'change-on-select is removed, use `props.checkStrictly` instead.',
486
+ 'hover-threshold': 'hover-threshold is removed, use `props.hoverThreshold` instead'
487
+ },
488
+ events: {
489
+ 'active-item-change': 'active-item-change is renamed to expand-change'
490
+ }
491
+ };
492
+ },
493
+ toggleDropDownVisible(visible) {
494
+ if (this.isDisabled) return;
495
+
496
+ const { dropDownVisible } = this;
497
+ const { input } = this.$refs;
498
+ visible = isDef(visible) ? visible : !dropDownVisible;
499
+ if (visible !== dropDownVisible) {
500
+ this.dropDownVisible = visible;
501
+ if (visible) {
502
+ this.$nextTick(() => {
503
+ this.updatePopper();
504
+ this.panel.scrollIntoView();
505
+ });
506
+ }
507
+ input.$refs.input.setAttribute('aria-expanded', visible);
508
+ this.$emit('visible-change', visible);
509
+ }
510
+ },
511
+ handleDropdownLeave() {
512
+ this.filtering = false;
513
+ this.inputValue = this.presentText;
514
+ this.doDestroy();
515
+ },
516
+ handleKeyDown(event) {
517
+ switch (event.keyCode) {
518
+ case KeyCode.enter:
519
+ this.toggleDropDownVisible();
520
+ break;
521
+ case KeyCode.down:
522
+ this.toggleDropDownVisible(true);
523
+ this.focusFirstNode();
524
+ event.preventDefault();
525
+ break;
526
+ case KeyCode.esc:
527
+ case KeyCode.tab:
528
+ this.toggleDropDownVisible(false);
529
+ break;
530
+ }
531
+ },
532
+ handleFocus(e) {
533
+ this.$emit('focus', e);
534
+ },
535
+ handleBlur(e) {
536
+ this.$emit('blur', e);
537
+ },
538
+ handleInput(val, event) {
539
+ !this.dropDownVisible && this.toggleDropDownVisible(true);
540
+
541
+ if (event && event.isComposing) return;
542
+ if (val) {
543
+ this.filterHandler();
544
+ } else {
545
+ this.filtering = false;
546
+ }
547
+ },
548
+ handleClear() {
549
+ this.presentText = '';
550
+ this.panel.clearCheckedNodes();
551
+ },
552
+ handleExpandChange(value) {
553
+ this.$nextTick(this.updatePopper.bind(this));
554
+ this.$emit('expand-change', value);
555
+ this.$emit('active-item-change', value); // Deprecated
556
+ },
557
+ focusFirstNode() {
558
+ this.$nextTick(() => {
559
+ const { filtering } = this;
560
+ const { popper, suggestionPanel } = this.$refs;
561
+ let firstNode = null;
562
+
563
+ if (filtering && suggestionPanel) {
564
+ firstNode = suggestionPanel.$el.querySelector('.el-cascader__suggestion-item');
565
+ } else {
566
+ const firstMenu = popper.querySelector('.el-cascader-menu');
567
+ firstNode = firstMenu.querySelector('.el-cascader-node[tabindex="-1"]');
568
+ }
569
+
570
+ if (firstNode) {
571
+ firstNode.focus();
572
+ !filtering && firstNode.click();
573
+ }
574
+ });
575
+ },
576
+ computePresentContent() {
577
+ // nextTick is required, because checked nodes may not change right now
578
+ this.$nextTick(() => {
579
+ if (this.config.multiple) {
580
+ this.computePresentTags();
581
+ this.presentText = this.presentTags.length ? ' ' : null;
582
+ } else {
583
+ this.computePresentText();
584
+ }
585
+ });
586
+ },
587
+ isEmptyValue(val) {
588
+ const { multiple } = this;
589
+ const { emitPath } = this.panel.config;
590
+ if (multiple || emitPath) {
591
+ return isEmpty(val);
592
+ }
593
+ return false;
594
+ },
595
+ computePresentText() {
596
+ const { checkedValue, config } = this;
597
+ if (!this.isEmptyValue(checkedValue)) {
598
+ const node = this.panel.getNodeByValue(checkedValue);
599
+ if (node && (config.checkStrictly || node.isLeaf)) {
600
+ this.presentText = node.getText(this.showAllLevels, this.separator);
601
+ return;
602
+ }
603
+ }
604
+ this.presentText = null;
605
+ },
606
+ computePresentTags() {
607
+ const { isDisabled, leafOnly, showAllLevels, separator } = this;
608
+ const checkedNodes = this.getCheckedNodes(leafOnly);
609
+ const tags = [];
610
+
611
+ const genTag = node => ({
612
+ node,
613
+ key: node.uid,
614
+ text: node.getText(showAllLevels, separator),
615
+ hitState: false,
616
+ closable: !isDisabled && !node.isDisabled
617
+ });
618
+
619
+ if (checkedNodes.length) {
620
+ checkedNodes.forEach(node => tags.push(genTag(node)));
621
+ // const [first, ...rest] = checkedNodes;
622
+ // const restCount = rest.length;
623
+ // tags.push(genTag(first));
624
+
625
+ // console.log(restCount, 'restCount============');
626
+ // this.restCount = restCount;
627
+ // if (restCount) {
628
+ // if (collapseTags) {
629
+ // tags.push({
630
+ // key: -1,
631
+ // text: `+${restCount}`,
632
+ // closable: false
633
+ // });
634
+ // } else {
635
+ // rest.forEach(node => tags.push(genTag(node)));
636
+ // }
637
+ // }
638
+ }
639
+
640
+ this.checkedNodes = checkedNodes;
641
+ this.presentTags = tags;
642
+ this.getMaxWidth();
643
+ },
644
+ getSuggestions() {
645
+ let { filterMethod } = this;
646
+
647
+ if (!isFunction(filterMethod)) {
648
+ filterMethod = (node, keyword) => node.text.includes(keyword);
649
+ }
650
+
651
+ const suggestions = this.panel.getFlattedNodes(this.leafOnly)
652
+ .filter(node => {
653
+ if (node.isDisabled) return false;
654
+ node.text = node.getText(this.showAllLevels, this.separator) || '';
655
+ return filterMethod(node, this.inputValue);
656
+ });
657
+
658
+ if (this.multiple) {
659
+ this.presentTags.forEach(tag => {
660
+ tag.hitState = false;
661
+ });
662
+ } else {
663
+ suggestions.forEach(node => {
664
+ node.checked = isEqual(this.checkedValue, node.getValueByOption());
665
+ });
666
+ }
667
+
668
+ this.filtering = true;
669
+ this.suggestions = suggestions;
670
+ this.$nextTick(this.updatePopper);
671
+ },
672
+ handleSuggestionKeyDown(event) {
673
+ const { keyCode, target } = event;
674
+ switch (keyCode) {
675
+ case KeyCode.enter:
676
+ target.click();
677
+ break;
678
+ case KeyCode.up:
679
+ const prev = target.previousElementSibling;
680
+ prev && prev.focus();
681
+ break;
682
+ case KeyCode.down:
683
+ const next = target.nextElementSibling;
684
+ next && next.focus();
685
+ break;
686
+ case KeyCode.esc:
687
+ case KeyCode.tab:
688
+ this.toggleDropDownVisible(false);
689
+ break;
690
+ }
691
+ },
692
+ handleDelete() {
693
+ const { inputValue, pressDeleteCount, presentTags } = this;
694
+ const lastIndex = presentTags.length - 1;
695
+ const lastTag = presentTags[lastIndex];
696
+ this.pressDeleteCount = inputValue ? 0 : pressDeleteCount + 1;
697
+
698
+ if (!lastTag) return;
699
+
700
+ if (this.pressDeleteCount) {
701
+ if (lastTag.hitState) {
702
+ this.deleteTag(lastTag);
703
+ } else {
704
+ lastTag.hitState = true;
705
+ }
706
+ }
707
+ },
708
+ handleSuggestionClick(index) {
709
+ const { multiple } = this;
710
+ const targetNode = this.suggestions[index];
711
+
712
+ if (multiple) {
713
+ const { checked } = targetNode;
714
+ targetNode.doCheck(!checked);
715
+ this.panel.calculateMultiCheckedValue();
716
+ } else {
717
+ this.checkedValue = targetNode.getValueByOption();
718
+ this.toggleDropDownVisible(false);
719
+ }
720
+ },
721
+ deleteTag(tag) {
722
+ const { checkedValue } = this;
723
+ const current = tag.node.getValueByOption();
724
+ const val = checkedValue.find(n => isEqual(n, current));
725
+ this.checkedValue = checkedValue.filter(n => !isEqual(n, current));
726
+ this.$emit('remove-tag', val);
727
+ },
728
+ updateStyle() {
729
+ const { $el, inputInitialHeight } = this;
730
+ if (this.$isServer || !$el) return;
731
+
732
+ const { suggestionPanel } = this.$refs;
733
+ const inputInner = $el.querySelector('.el-input__inner');
734
+
735
+ if (!inputInner) return;
736
+
737
+ const tags = $el.querySelector('.el-cascader__tags');
738
+ const groupPrefix = $el.querySelector('.el-input-group--prefix');
739
+ const prefixLabel = $el.querySelector('.el-input-group__prefix-label');
740
+ let suggestionPanelEl = null;
741
+
742
+ if (suggestionPanel && (suggestionPanelEl = suggestionPanel.$el)) {
743
+ const suggestionList = suggestionPanelEl.querySelector('.el-cascader__suggestion-list');
744
+ suggestionList.style.minWidth = inputInner.offsetWidth + 'px';
745
+ }
746
+
747
+ if (tags) {
748
+ const offsetHeight = Math.round(tags.getBoundingClientRect().height);
749
+ const height = Math.max(offsetHeight + 4, inputInitialHeight) + 'px';
750
+ const inputPaddingLeft = Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) || 0;
751
+ const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
752
+ if (groupPrefix) {
753
+ groupPrefix.style.height = height;
754
+ } else {
755
+ inputInner.style.height = height;
756
+ }
757
+ tags.style.left = prefixLabel ? (prefixLabelWidth + inputPaddingLeft - 4) + 'px' : '0px';
758
+ if (this.checkedNodes.length === 0 && !prefixLabel) {
759
+ tags.style.left = '12px';
760
+ }
761
+ if (this.dropDownVisible) {
762
+ this.updatePopper();
763
+ }
764
+ }
765
+ },
766
+
767
+ /**
768
+ * public methods
769
+ */
770
+ getCheckedNodes(leafOnly) {
771
+ return this.panel.getCheckedNodes(leafOnly);
772
+ }
773
+ }
774
+ };
775
+ </script>
776
+