yy-vue-easytable 2.27.2

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 (205) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +187 -0
  3. package/libs/font/demo.css +539 -0
  4. package/libs/font/demo_index.html +400 -0
  5. package/libs/font/iconfont.css +57 -0
  6. package/libs/font/iconfont.eot +0 -0
  7. package/libs/font/iconfont.js +1 -0
  8. package/libs/font/iconfont.json +79 -0
  9. package/libs/font/iconfont.svg +56 -0
  10. package/libs/font/iconfont.ttf +0 -0
  11. package/libs/font/iconfont.woff +0 -0
  12. package/libs/font/iconfont.woff2 +0 -0
  13. package/libs/locale/lang/af-ZA.js +48 -0
  14. package/libs/locale/lang/en-US.js +48 -0
  15. package/libs/locale/lang/fr-FR.js +48 -0
  16. package/libs/locale/lang/ko-KR.js +48 -0
  17. package/libs/locale/lang/pt-BR.js +48 -0
  18. package/libs/locale/lang/ru-RU.js +48 -0
  19. package/libs/locale/lang/zh-CN.js +48 -0
  20. package/libs/locale/lang/zh-TW.js +48 -0
  21. package/libs/locale/lang/zu-ZA.js +48 -0
  22. package/libs/main.js +1 -0
  23. package/libs/theme-dark/base.css +1 -0
  24. package/libs/theme-dark/index.css +1253 -0
  25. package/libs/theme-dark/var.css +7 -0
  26. package/libs/theme-dark/ve-checkbox.css +150 -0
  27. package/libs/theme-dark/ve-contextmenu.css +71 -0
  28. package/libs/theme-dark/ve-dropdown.css +177 -0
  29. package/libs/theme-dark/ve-icon.css +10 -0
  30. package/libs/theme-dark/ve-loading.css +218 -0
  31. package/libs/theme-dark/ve-pagination.css +136 -0
  32. package/libs/theme-dark/ve-radio.css +111 -0
  33. package/libs/theme-dark/ve-select.css +50 -0
  34. package/libs/theme-dark/ve-table.css +385 -0
  35. package/libs/theme-default/base.css +1 -0
  36. package/libs/theme-default/index.css +1253 -0
  37. package/libs/theme-default/var.css +7 -0
  38. package/libs/theme-default/ve-checkbox.css +150 -0
  39. package/libs/theme-default/ve-contextmenu.css +71 -0
  40. package/libs/theme-default/ve-dropdown.css +177 -0
  41. package/libs/theme-default/ve-icon.css +10 -0
  42. package/libs/theme-default/ve-loading.css +218 -0
  43. package/libs/theme-default/ve-pagination.css +136 -0
  44. package/libs/theme-default/ve-radio.css +111 -0
  45. package/libs/theme-default/ve-select.css +50 -0
  46. package/libs/theme-default/ve-table.css +385 -0
  47. package/libs/umd/index.js +9 -0
  48. package/libs/ve-checkbox-group.js +1 -0
  49. package/libs/ve-checkbox.js +1 -0
  50. package/libs/ve-contextmenu.js +1 -0
  51. package/libs/ve-dropdown.js +1 -0
  52. package/libs/ve-icon.js +1 -0
  53. package/libs/ve-loading.js +1 -0
  54. package/libs/ve-locale.js +1 -0
  55. package/libs/ve-pagination.js +1 -0
  56. package/libs/ve-radio.js +1 -0
  57. package/libs/ve-select.js +1 -0
  58. package/libs/ve-table.js +1 -0
  59. package/package.json +142 -0
  60. package/packages/font/demo.css +539 -0
  61. package/packages/font/demo_index.html +400 -0
  62. package/packages/font/iconfont.css +57 -0
  63. package/packages/font/iconfont.eot +0 -0
  64. package/packages/font/iconfont.js +1 -0
  65. package/packages/font/iconfont.json +79 -0
  66. package/packages/font/iconfont.svg +56 -0
  67. package/packages/font/iconfont.ttf +0 -0
  68. package/packages/font/iconfont.woff +0 -0
  69. package/packages/font/iconfont.woff2 +0 -0
  70. package/packages/index.js +75 -0
  71. package/packages/src/comps/resize-observer/index.js +2 -0
  72. package/packages/src/comps/resize-observer/src/index.jsx +38 -0
  73. package/packages/src/directives/clickoutside.js +31 -0
  74. package/packages/src/directives/events-outside.js +79 -0
  75. package/packages/src/directives/focus.js +28 -0
  76. package/packages/src/locale/index.js +27 -0
  77. package/packages/src/locale/lang/af-ZA.js +29 -0
  78. package/packages/src/locale/lang/en-US.js +30 -0
  79. package/packages/src/locale/lang/fr-FR.js +29 -0
  80. package/packages/src/locale/lang/ko-KR.js +29 -0
  81. package/packages/src/locale/lang/pt-BR.js +29 -0
  82. package/packages/src/locale/lang/ru-RU.js +29 -0
  83. package/packages/src/locale/lang/zh-CN.js +30 -0
  84. package/packages/src/locale/lang/zh-TW.js +29 -0
  85. package/packages/src/locale/lang/zu-ZA.js +29 -0
  86. package/packages/src/mixins/emitter.js +39 -0
  87. package/packages/src/utils/animation-frame.js +39 -0
  88. package/packages/src/utils/auto-resize.js +179 -0
  89. package/packages/src/utils/constant.js +42 -0
  90. package/packages/src/utils/dom.js +239 -0
  91. package/packages/src/utils/event-key-codes.js +53 -0
  92. package/packages/src/utils/hooks-manager.js +76 -0
  93. package/packages/src/utils/index.js +161 -0
  94. package/packages/src/utils/mouse-event.js +24 -0
  95. package/packages/src/utils/random.js +6 -0
  96. package/packages/src/utils/request-animation-timeout.js +36 -0
  97. package/packages/src/utils/resize-event.js +40 -0
  98. package/packages/src/utils/scroll-bar.js +27 -0
  99. package/packages/style/ve-checkbox.less +179 -0
  100. package/packages/style/ve-contextmenu.less +76 -0
  101. package/packages/style/ve-dropdown.less +204 -0
  102. package/packages/style/ve-icon.less +3 -0
  103. package/packages/style/ve-loading.less +242 -0
  104. package/packages/style/ve-pagination.less +153 -0
  105. package/packages/style/ve-radio.less +126 -0
  106. package/packages/style/ve-select.less +48 -0
  107. package/packages/style/ve-table.less +539 -0
  108. package/packages/theme-dark/base.less +1 -0
  109. package/packages/theme-dark/index.less +12 -0
  110. package/packages/theme-dark/var.less +111 -0
  111. package/packages/theme-dark/ve-checkbox.less +2 -0
  112. package/packages/theme-dark/ve-contextmenu.less +2 -0
  113. package/packages/theme-dark/ve-dropdown.less +2 -0
  114. package/packages/theme-dark/ve-icon.less +2 -0
  115. package/packages/theme-dark/ve-loading.less +2 -0
  116. package/packages/theme-dark/ve-pagination.less +2 -0
  117. package/packages/theme-dark/ve-radio.less +2 -0
  118. package/packages/theme-dark/ve-select.less +2 -0
  119. package/packages/theme-dark/ve-table.less +2 -0
  120. package/packages/theme-default/base.less +1 -0
  121. package/packages/theme-default/index.less +12 -0
  122. package/packages/theme-default/var.less +111 -0
  123. package/packages/theme-default/ve-checkbox.less +2 -0
  124. package/packages/theme-default/ve-contextmenu.less +2 -0
  125. package/packages/theme-default/ve-dropdown.less +2 -0
  126. package/packages/theme-default/ve-icon.less +2 -0
  127. package/packages/theme-default/ve-loading.less +2 -0
  128. package/packages/theme-default/ve-pagination.less +2 -0
  129. package/packages/theme-default/ve-radio.less +2 -0
  130. package/packages/theme-default/ve-select.less +2 -0
  131. package/packages/theme-default/ve-table.less +2 -0
  132. package/packages/ve-checkbox/index.js +7 -0
  133. package/packages/ve-checkbox/src/index.jsx +175 -0
  134. package/packages/ve-checkbox/src/util/constant.js +14 -0
  135. package/packages/ve-checkbox/src/util/index.js +10 -0
  136. package/packages/ve-checkbox-group/index.js +7 -0
  137. package/packages/ve-checkbox-group/src/index.jsx +53 -0
  138. package/packages/ve-checkbox-group/src/util/constant.js +14 -0
  139. package/packages/ve-checkbox-group/src/util/index.js +10 -0
  140. package/packages/ve-contextmenu/index.js +7 -0
  141. package/packages/ve-contextmenu/src/index.jsx +731 -0
  142. package/packages/ve-contextmenu/src/util/constant.js +29 -0
  143. package/packages/ve-contextmenu/src/util/index.js +10 -0
  144. package/packages/ve-dropdown/index.js +7 -0
  145. package/packages/ve-dropdown/src/index.jsx +720 -0
  146. package/packages/ve-dropdown/src/util/constant.js +15 -0
  147. package/packages/ve-dropdown/src/util/index.js +10 -0
  148. package/packages/ve-icon/index.js +7 -0
  149. package/packages/ve-icon/src/index.jsx +52 -0
  150. package/packages/ve-icon/src/util/constant.js +10 -0
  151. package/packages/ve-icon/src/util/index.js +10 -0
  152. package/packages/ve-loading/index.js +8 -0
  153. package/packages/ve-loading/src/bounce.jsx +50 -0
  154. package/packages/ve-loading/src/flow.jsx +51 -0
  155. package/packages/ve-loading/src/grid.jsx +57 -0
  156. package/packages/ve-loading/src/index.js +106 -0
  157. package/packages/ve-loading/src/loading.jsx +63 -0
  158. package/packages/ve-loading/src/plane.jsx +38 -0
  159. package/packages/ve-loading/src/pulse.jsx +38 -0
  160. package/packages/ve-loading/src/util/constant.js +31 -0
  161. package/packages/ve-loading/src/util/index.js +10 -0
  162. package/packages/ve-loading/src/wave.jsx +53 -0
  163. package/packages/ve-locale/index.js +28 -0
  164. package/packages/ve-pagination/index.js +7 -0
  165. package/packages/ve-pagination/src/index.jsx +304 -0
  166. package/packages/ve-pagination/src/pager.jsx +166 -0
  167. package/packages/ve-pagination/src/util/constant.js +16 -0
  168. package/packages/ve-pagination/src/util/index.js +10 -0
  169. package/packages/ve-radio/index.js +7 -0
  170. package/packages/ve-radio/src/index.jsx +121 -0
  171. package/packages/ve-radio/src/util/constant.js +13 -0
  172. package/packages/ve-radio/src/util/index.js +10 -0
  173. package/packages/ve-select/index.js +7 -0
  174. package/packages/ve-select/src/index.jsx +193 -0
  175. package/packages/ve-select/src/util/constant.js +13 -0
  176. package/packages/ve-select/src/util/index.js +10 -0
  177. package/packages/ve-table/index.js +7 -0
  178. package/packages/ve-table/src/body/body-checkbox-content.jsx +126 -0
  179. package/packages/ve-table/src/body/body-radio-content.jsx +113 -0
  180. package/packages/ve-table/src/body/body-td.jsx +671 -0
  181. package/packages/ve-table/src/body/body-tr-scrolling.jsx +38 -0
  182. package/packages/ve-table/src/body/body-tr.jsx +383 -0
  183. package/packages/ve-table/src/body/expand-tr-icon.jsx +80 -0
  184. package/packages/ve-table/src/body/expand-tr.jsx +147 -0
  185. package/packages/ve-table/src/body/index.jsx +943 -0
  186. package/packages/ve-table/src/colgroup/index.jsx +48 -0
  187. package/packages/ve-table/src/column-resizer/index.jsx +318 -0
  188. package/packages/ve-table/src/editor/constant.js +5 -0
  189. package/packages/ve-table/src/editor/index.jsx +533 -0
  190. package/packages/ve-table/src/footer/footer-td.jsx +396 -0
  191. package/packages/ve-table/src/footer/footer-tr.jsx +249 -0
  192. package/packages/ve-table/src/footer/index.jsx +108 -0
  193. package/packages/ve-table/src/header/header-checkbox-content.jsx +69 -0
  194. package/packages/ve-table/src/header/header-filter-content.jsx +100 -0
  195. package/packages/ve-table/src/header/header-filter-custom-content.jsx +110 -0
  196. package/packages/ve-table/src/header/header-th.jsx +664 -0
  197. package/packages/ve-table/src/header/header-tr.jsx +255 -0
  198. package/packages/ve-table/src/header/index.jsx +195 -0
  199. package/packages/ve-table/src/index.jsx +4196 -0
  200. package/packages/ve-table/src/selection/constant.js +5 -0
  201. package/packages/ve-table/src/selection/index.jsx +1643 -0
  202. package/packages/ve-table/src/util/clipboard.js +428 -0
  203. package/packages/ve-table/src/util/constant.js +269 -0
  204. package/packages/ve-table/src/util/index.js +1585 -0
  205. package/packages/ve-table/src/util/store.js +14 -0
@@ -0,0 +1,731 @@
1
+ import { COMPS_NAME } from "./util/constant";
2
+ import { clsName } from "./util/index";
3
+ import VeIcon from "vue-easytable/packages/ve-icon";
4
+ import { ICON_NAMES } from "../../src/utils/constant";
5
+ import { getMousePosition, getViewportOffset } from "../../src/utils/dom";
6
+ import {
7
+ INIT_DATA,
8
+ EMIT_EVENTS,
9
+ CONTEXTMENU_NODE_TYPES,
10
+ INSTANCE_METHODS,
11
+ } from "./util/constant";
12
+ import { getRandomId } from "../../src/utils/random";
13
+ import { debounce, cloneDeep } from "lodash";
14
+ import eventsOutside from "../../src/directives/events-outside";
15
+
16
+ export default {
17
+ name: COMPS_NAME.VE_CONTEXTMENU,
18
+ directives: {
19
+ "events-outside": eventsOutside,
20
+ },
21
+ props: {
22
+ /*
23
+ options(contextmenu)
24
+ [
25
+ {
26
+
27
+ id: 1,
28
+ label: "菜单1",
29
+ disabled:true
30
+ },
31
+ {
32
+ id: 2,
33
+ label: "菜单2",
34
+ children: [
35
+ {
36
+ id: "2-1",
37
+ label: "菜单2-1",
38
+ },
39
+ {
40
+ id: "2-2",
41
+ label: "菜单2-2",
42
+ },
43
+ ],
44
+ },
45
+ ]
46
+ */
47
+ options: {
48
+ type: Array,
49
+ required: true,
50
+ },
51
+ /*
52
+ event target
53
+ contextmenu event will register on it
54
+ */
55
+ eventTarget: {
56
+ type: [String, HTMLElement],
57
+ required: true,
58
+ },
59
+ },
60
+ data() {
61
+ return {
62
+ /*
63
+ internal options:
64
+ [
65
+ {
66
+ id: 1,
67
+ deep: 0,
68
+ hasChildren: false,
69
+ label: "菜单1",
70
+ },
71
+ {
72
+ id: 2,
73
+ label: "菜单2",
74
+ deep: 0,
75
+ hasChildren: true,
76
+ children: [
77
+ {
78
+ id: "2-1",
79
+ deep: 1,
80
+ hasChildren: false,
81
+ label: "菜单2-1",
82
+ },
83
+ {
84
+ id: "2-2",
85
+ deep: 1,
86
+ hasChildren: false,
87
+ label: "菜单2-2",
88
+ },
89
+ ],
90
+ },
91
+ ]
92
+ */
93
+ internalOptions: [],
94
+
95
+ /*
96
+ panels option
97
+ {
98
+ id: 1,
99
+ menus: [
100
+ {
101
+ id: "",
102
+ deep: 0,
103
+ label: "菜单1",
104
+ hasChildren: true,
105
+ },
106
+ {
107
+ id: "",
108
+ deep: 0,
109
+ label: "菜单2",
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ id: 2,
115
+ menus: [
116
+ {
117
+ id: "",
118
+ deep: 1,
119
+ label: "菜单1",
120
+ hasChildren: true,
121
+ },
122
+ {
123
+ id: "",
124
+ deep: 1,
125
+ label: "菜单2",
126
+ },
127
+ ],
128
+ },
129
+ */
130
+ panelOptions: [],
131
+ // event target element
132
+ eventTargetEl: "",
133
+ // root contextmenu id
134
+ rootContextmenuId: "",
135
+ /*
136
+ is children panels clicked
137
+ 如果点击了则不关闭 panels
138
+ */
139
+ isChildrenPanelsClicked: false,
140
+ /*
141
+ is panel right direction
142
+ 决定了子 panel 默认展示方向
143
+ */
144
+ isPanelRightDirection: true,
145
+ /*
146
+ is panels remove
147
+ 防止hover后菜单被移除,仍然显示子集菜单的问题
148
+ */
149
+ isPanelsEmptyed: true,
150
+ };
151
+ },
152
+
153
+ computed: {
154
+ // active menus ids
155
+ activeMenuIds() {
156
+ const { panelOptions } = this;
157
+
158
+ return panelOptions.map((x) => x.parentId);
159
+ },
160
+ },
161
+
162
+ watch: {
163
+ options: {
164
+ handler: function (val) {
165
+ if (Array.isArray(val) && val.length > 0) {
166
+ /*
167
+ 如果配置项修改,则重新销毁并创建
168
+ */
169
+ this.removeOrEmptyPanels(true);
170
+ this.rootContextmenuId = this.getRandomIdWithPrefix();
171
+ this.createInternalOptions();
172
+ this.createPanelOptions({ options: this.internalOptions });
173
+ this.resetContextmenu();
174
+ this.addRootContextmenuPanelToBody();
175
+ }
176
+ },
177
+ immediate: true,
178
+ },
179
+ eventTarget: {
180
+ handler: function (val) {
181
+ if (val) {
182
+ this.registerContextmenuEvent();
183
+ }
184
+ },
185
+ immediate: true,
186
+ },
187
+ },
188
+
189
+ methods: {
190
+ // get random id
191
+ getRandomIdWithPrefix() {
192
+ return clsName(getRandomId());
193
+ },
194
+
195
+ // has children
196
+ hasChildren(option) {
197
+ return Array.isArray(option.children) && option.children.length;
198
+ },
199
+
200
+ /*
201
+ get panel option by menu id
202
+ */
203
+ getPanelOptionByMenuId(options, menuId) {
204
+ for (let i = 0; i < options.length; i++) {
205
+ if (options[i].id === menuId) {
206
+ return options[i].children;
207
+ }
208
+
209
+ if (options[i].children) {
210
+ const panelOption = this.getPanelOptionByMenuId(
211
+ options[i].children,
212
+ menuId,
213
+ );
214
+ if (panelOption) return panelOption;
215
+ }
216
+ }
217
+ },
218
+
219
+ // get parent contextmenu panel element
220
+ getParentContextmenuPanelEl(contextmenuPanelId) {
221
+ let result;
222
+
223
+ const { panelOptions } = this;
224
+
225
+ const panelIndex = panelOptions.findIndex(
226
+ (x) => x.parentId === contextmenuPanelId,
227
+ );
228
+ if (panelIndex > 0) {
229
+ // preview panel's panelId
230
+ const parentPanelId = panelOptions[panelIndex - 1].parentId;
231
+ result = document.querySelector(`#${parentPanelId}`);
232
+ }
233
+ return result;
234
+ },
235
+
236
+ // create panel by hover
237
+ createPanelByHover({ event, menu }) {
238
+ const { internalOptions, panelOptions } = this;
239
+
240
+ // 如果被移除则不创建
241
+ if (this.isPanelsEmptyed) {
242
+ return false;
243
+ }
244
+
245
+ // has already exists
246
+ if (panelOptions.findIndex((x) => x.parentId === menu.id) > -1) {
247
+ return false;
248
+ }
249
+
250
+ /*
251
+ 移除 panel 深度大于等于当前悬浮菜单的。从后往前删除
252
+ remove panels
253
+ */
254
+ const deletePanelDeeps = panelOptions
255
+ .filter((x) => x.parentDeep >= menu.deep)
256
+ .map((x) => x.parentDeep)
257
+ .reverse();
258
+
259
+ if (deletePanelDeeps.length) {
260
+ for (let i = deletePanelDeeps.length - 1; i >= 0; i--) {
261
+ const delIndex = panelOptions.findIndex(
262
+ (x) => x.parentDeep === deletePanelDeeps[i],
263
+ );
264
+ if (delIndex > -1) {
265
+ this.panelOptions.splice(delIndex, 1);
266
+ }
267
+ }
268
+ }
269
+
270
+ const panelOption = this.getPanelOptionByMenuId(
271
+ internalOptions,
272
+ menu.id,
273
+ );
274
+
275
+ if (panelOption) {
276
+ this.createPanelOptions({
277
+ options: panelOption,
278
+ currentMenu: menu,
279
+ });
280
+
281
+ this.$nextTick(() => {
282
+ this.addContextmenuPanelToBody({
283
+ contextmenuId: menu.id,
284
+ });
285
+
286
+ this.showContextmenuPanel({
287
+ event,
288
+ contextmenuId: menu.id,
289
+ });
290
+ });
291
+ }
292
+ },
293
+
294
+ // create panels option
295
+ createPanelOptions({ options, currentMenu }) {
296
+ const { hasChildren, rootContextmenuId } = this;
297
+
298
+ if (Array.isArray(options)) {
299
+ //
300
+ let menus = options.map((option) => {
301
+ return {
302
+ hasChildren: hasChildren(option),
303
+ ...option,
304
+ };
305
+ });
306
+
307
+ this.panelOptions.push({
308
+ parentId: currentMenu ? currentMenu.id : rootContextmenuId,
309
+ parentDeep: currentMenu
310
+ ? currentMenu.deep
311
+ : INIT_DATA.PARENT_DEEP,
312
+ menus: menus,
313
+ });
314
+ }
315
+ },
316
+
317
+ // create internal options recursion
318
+ createInternalOptionsRecursion(options, deep = 0) {
319
+ options.id = this.getRandomIdWithPrefix();
320
+ options.deep = deep;
321
+ deep++;
322
+ if (Array.isArray(options.children)) {
323
+ options.children.map((option) => {
324
+ return this.createInternalOptionsRecursion(option, deep);
325
+ });
326
+ }
327
+
328
+ return options;
329
+ },
330
+
331
+ // create internal options
332
+ createInternalOptions() {
333
+ this.internalOptions = cloneDeep(this.options).map((option) => {
334
+ return this.createInternalOptionsRecursion(option);
335
+ });
336
+ },
337
+
338
+ // show root contextmenu panel
339
+ showRootContextmenuPanel(event) {
340
+ event.preventDefault();
341
+ const { rootContextmenuId } = this;
342
+
343
+ if (rootContextmenuId) {
344
+ // refresh contextmenu
345
+ this.resetContextmenu();
346
+ this.showContextmenuPanel({
347
+ event,
348
+ contextmenuId: rootContextmenuId,
349
+ isRootContextmenu: true,
350
+ });
351
+ this.isPanelsEmptyed = false;
352
+ }
353
+ },
354
+
355
+ // show contextmenu panel
356
+ showContextmenuPanel({ event, contextmenuId, isRootContextmenu }) {
357
+ const { getParentContextmenuPanelEl } = this;
358
+
359
+ let contextmenuPanelEl = document.querySelector(
360
+ `#${contextmenuId}`,
361
+ );
362
+
363
+ if (contextmenuPanelEl) {
364
+ // remove first
365
+ contextmenuPanelEl.innerHTML = "";
366
+
367
+ contextmenuPanelEl.appendChild(this.$refs[contextmenuId]);
368
+
369
+ contextmenuPanelEl.style.position = "absolute";
370
+ contextmenuPanelEl.classList.add(clsName("popper"));
371
+
372
+ const { width: currentPanelWidth, height: currentPanelHeight } =
373
+ contextmenuPanelEl.getBoundingClientRect();
374
+ if (isRootContextmenu) {
375
+ const {
376
+ left: clickLeft,
377
+ top: clickTop,
378
+ right: clickRight,
379
+ bottom: clickBottom,
380
+ } = getMousePosition(event);
381
+
382
+ let panelX = 0;
383
+ let panelY = 0;
384
+
385
+ // 右方宽度够显示
386
+ if (clickRight >= currentPanelWidth) {
387
+ panelX = clickLeft;
388
+ this.isPanelRightDirection = true;
389
+ }
390
+ // 右方宽度不够显示在鼠标点击左方
391
+ else {
392
+ panelX = clickLeft - currentPanelWidth;
393
+ this.isPanelRightDirection = false;
394
+ }
395
+
396
+ // 下方高度够显示
397
+ if (clickBottom >= currentPanelHeight) {
398
+ panelY = clickTop;
399
+ }
400
+ // 下方高度不够显示在鼠标点击上方
401
+ else {
402
+ panelY = clickTop - currentPanelHeight;
403
+ }
404
+
405
+ contextmenuPanelEl.style.left = panelX + "px";
406
+ contextmenuPanelEl.style.top = panelY + "px";
407
+ } else {
408
+ const parentContextmenuPanelEl =
409
+ getParentContextmenuPanelEl(contextmenuId);
410
+
411
+ if (parentContextmenuPanelEl) {
412
+ const {
413
+ left: parentPanelLeft,
414
+ right: parentPanelRight,
415
+ } = getViewportOffset(parentContextmenuPanelEl);
416
+
417
+ const { top: clickTop, bottom: clickBottom } =
418
+ getMousePosition(event);
419
+
420
+ const { width: parentPanelWidth } =
421
+ parentContextmenuPanelEl.getBoundingClientRect();
422
+
423
+ let panelX = 0;
424
+ let panelY = 0;
425
+
426
+ // 如果默认展示在右方向
427
+ if (this.isPanelRightDirection) {
428
+ // 右方宽度够显示
429
+ if (parentPanelRight >= currentPanelWidth) {
430
+ panelX = parentPanelLeft + parentPanelWidth;
431
+ }
432
+ // 右方宽度不够显示在鼠标点击左方
433
+ else {
434
+ panelX = parentPanelLeft - parentPanelWidth;
435
+ }
436
+ }
437
+ // 如果默认展示在左方向
438
+ else {
439
+ // 左方宽度够显示
440
+ if (parentPanelLeft >= currentPanelWidth) {
441
+ panelX = parentPanelLeft - parentPanelWidth;
442
+ }
443
+ // 左方宽度不够显示在鼠标点击右方
444
+ else {
445
+ panelX = parentPanelLeft + parentPanelWidth;
446
+ }
447
+ }
448
+
449
+ // 下方高度够显示
450
+ if (clickBottom >= currentPanelHeight) {
451
+ panelY = clickTop;
452
+ }
453
+ // 下方高度不够显示在鼠标点击上方
454
+ else {
455
+ panelY = clickTop - currentPanelHeight;
456
+ }
457
+
458
+ contextmenuPanelEl.style.left = panelX + "px";
459
+ contextmenuPanelEl.style.top = panelY + "px";
460
+ }
461
+ }
462
+ }
463
+ },
464
+
465
+ // empty contextmenu panels
466
+ emptyContextmenuPanels() {
467
+ /*
468
+ wait for children panel clicked by setTimeout
469
+ 如果点击的是非 root panel 不关闭
470
+ */
471
+ setTimeout(() => {
472
+ if (this.isChildrenPanelsClicked) {
473
+ this.isChildrenPanelsClicked = false;
474
+ } else {
475
+ this.removeOrEmptyPanels();
476
+ this.isPanelsEmptyed = true;
477
+ }
478
+ });
479
+ },
480
+
481
+ // remove or empty panels
482
+ removeOrEmptyPanels(isRemove) {
483
+ const { panelOptions } = this;
484
+
485
+ panelOptions.forEach((panelOption) => {
486
+ let contextmenuPanelEl = document.querySelector(
487
+ `#${panelOption.parentId}`,
488
+ );
489
+ if (contextmenuPanelEl) {
490
+ if (isRemove) {
491
+ contextmenuPanelEl.remove();
492
+ } else {
493
+ contextmenuPanelEl.innerHTML = "";
494
+ }
495
+ }
496
+ });
497
+ },
498
+
499
+ // reset contextmeny
500
+ resetContextmenu() {
501
+ this.panelOptions = [];
502
+ this.createPanelOptions({ options: this.internalOptions });
503
+ },
504
+
505
+ // add context menu panel to body
506
+ addContextmenuPanelToBody({ contextmenuId }) {
507
+ let contextmenuPanelEl = document.querySelector(
508
+ `#${contextmenuId}`,
509
+ );
510
+
511
+ if (contextmenuPanelEl) {
512
+ return false;
513
+ } else {
514
+ let containerEl = document.createElement("div");
515
+
516
+ containerEl.setAttribute("id", contextmenuId);
517
+
518
+ document.body.appendChild(containerEl);
519
+ }
520
+ },
521
+
522
+ // add root contextmenu panel to body
523
+ addRootContextmenuPanelToBody() {
524
+ if (this.rootContextmenuId) {
525
+ this.addContextmenuPanelToBody({
526
+ contextmenuId: this.rootContextmenuId,
527
+ });
528
+ }
529
+ },
530
+
531
+ // register contextmenu event
532
+ registerContextmenuEvent() {
533
+ const { eventTarget } = this;
534
+
535
+ if (typeof eventTarget === "string" && eventTarget.length > 0) {
536
+ this.eventTargetEl = document.querySelector(eventTarget);
537
+ } else {
538
+ this.eventTargetEl = eventTarget;
539
+ }
540
+
541
+ if (this.eventTargetEl) {
542
+ // contextmenu is on the current element
543
+ this.eventTargetEl.addEventListener(
544
+ "contextmenu",
545
+ this.showRootContextmenuPanel,
546
+ );
547
+ }
548
+ },
549
+
550
+ // unregister contextmen event
551
+ removeContextmenuEvent() {
552
+ if (this.eventTargetEl) {
553
+ this.eventTargetEl.removeEventListener(
554
+ "contextmenu",
555
+ this.showRootContextmenuPanel,
556
+ );
557
+ }
558
+ },
559
+
560
+ // hide contextmenu
561
+ [INSTANCE_METHODS.HIDE_CONTEXTMENU]() {
562
+ this.emptyContextmenuPanels();
563
+ },
564
+ },
565
+
566
+ created() {
567
+ // bug fixed #467
568
+ this.debounceCreatePanelByHover = debounce(
569
+ this.createPanelByHover,
570
+ 300,
571
+ );
572
+ },
573
+
574
+ mounted() {
575
+ this.addRootContextmenuPanelToBody();
576
+ },
577
+
578
+ destroyed() {
579
+ this.removeContextmenuEvent();
580
+ this.removeOrEmptyPanels(true);
581
+ },
582
+
583
+ render() {
584
+ const {
585
+ panelOptions,
586
+ activeMenuIds,
587
+ hasChildren,
588
+ emptyContextmenuPanels,
589
+ debounceCreatePanelByHover,
590
+ } = this;
591
+
592
+ const contextmenuProps = {
593
+ class: ["ve-contextmenu"],
594
+ style: {
595
+ display: "none",
596
+ },
597
+ };
598
+
599
+ return (
600
+ <div {...contextmenuProps}>
601
+ {panelOptions.map((panelOption, panelIndex) => {
602
+ const contextmenuPanelProps = {
603
+ ref: panelOption.parentId,
604
+ class: {
605
+ [clsName("panel")]: true,
606
+ },
607
+ directives: [
608
+ {
609
+ name: "events-outside",
610
+ value: {
611
+ events: ["click"],
612
+ callback: (e) => {
613
+ // only for root panel
614
+ if (panelIndex === 0) {
615
+ emptyContextmenuPanels();
616
+ }
617
+ },
618
+ },
619
+ },
620
+ ],
621
+ on: {
622
+ click: () => {
623
+ if (panelIndex !== 0) {
624
+ this.isChildrenPanelsClicked = true;
625
+ }
626
+ },
627
+ contextmenu: (e) => {
628
+ e.preventDefault();
629
+ },
630
+ },
631
+ };
632
+ return (
633
+ <div {...contextmenuPanelProps}>
634
+ <ul class={clsName("list")}>
635
+ {panelOption.menus.map((menu) => {
636
+ let contextmenuNodeProps;
637
+
638
+ if (
639
+ menu.type !==
640
+ CONTEXTMENU_NODE_TYPES.SEPARATOR
641
+ ) {
642
+ contextmenuNodeProps = {
643
+ class: {
644
+ [clsName("node")]: true,
645
+ [clsName("node-active")]:
646
+ activeMenuIds.includes(
647
+ menu.id,
648
+ ),
649
+ [clsName("node-disabled")]:
650
+ menu.disabled,
651
+ },
652
+ on: {
653
+ mouseover: (event) => {
654
+ // disable
655
+ if (!menu.disabled) {
656
+ debounceCreatePanelByHover(
657
+ {
658
+ event,
659
+ menu,
660
+ },
661
+ );
662
+ }
663
+ },
664
+ click: () => {
665
+ if (
666
+ !menu.disabled &&
667
+ !hasChildren(menu)
668
+ ) {
669
+ this.$emit(
670
+ EMIT_EVENTS.ON_NODE_CLICK,
671
+ menu.type,
672
+ );
673
+ setTimeout(() => {
674
+ emptyContextmenuPanels();
675
+ }, 50);
676
+ }
677
+ },
678
+ },
679
+ };
680
+ }
681
+ // separator
682
+ else {
683
+ //
684
+ contextmenuNodeProps = {
685
+ class: {
686
+ [clsName(
687
+ "node-separator",
688
+ )]: true,
689
+ },
690
+ };
691
+ }
692
+
693
+ if (
694
+ menu.type !==
695
+ CONTEXTMENU_NODE_TYPES.SEPARATOR
696
+ ) {
697
+ return (
698
+ <li {...contextmenuNodeProps}>
699
+ <span
700
+ class={clsName(
701
+ "node-label",
702
+ )}
703
+ >
704
+ {menu.label}
705
+ </span>
706
+ {menu.hasChildren && (
707
+ <VeIcon
708
+ class={clsName(
709
+ "node-icon-postfix",
710
+ )}
711
+ name={
712
+ ICON_NAMES.RIGHT_ARROW
713
+ }
714
+ />
715
+ )}
716
+ </li>
717
+ );
718
+ } else {
719
+ return (
720
+ <li {...contextmenuNodeProps}></li>
721
+ );
722
+ }
723
+ })}
724
+ </ul>
725
+ </div>
726
+ );
727
+ })}
728
+ </div>
729
+ );
730
+ },
731
+ };