vue-editify 0.1.18 → 0.1.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. package/README.md +3 -3
  2. package/examples/App.vue +62 -61
  3. package/examples/main.ts +4 -4
  4. package/lib/components/button/button.vue.d.ts +11 -11
  5. package/lib/components/checkbox/checkbox.vue.d.ts +8 -8
  6. package/lib/components/colors/colors.vue.d.ts +4 -4
  7. package/lib/components/icon/icon.vue.d.ts +1 -1
  8. package/lib/components/insertImage/insertImage.vue.d.ts +9 -9
  9. package/lib/components/insertLink/insertLink.vue.d.ts +2 -2
  10. package/lib/components/insertTable/insertTable.vue.d.ts +2 -2
  11. package/lib/components/insertVideo/insertVideo.vue.d.ts +9 -9
  12. package/lib/components/layer/layer.vue.d.ts +9 -9
  13. package/lib/components/menu/menu.vue.d.ts +4 -4
  14. package/lib/components/toolbar/toolbar.vue.d.ts +9 -9
  15. package/lib/components/tooltip/tooltip.vue.d.ts +1 -1
  16. package/lib/components/triangle/triangle.vue.d.ts +4 -4
  17. package/lib/editify/editify.vue.d.ts +68 -68
  18. package/lib/editify.es.js +17 -17
  19. package/lib/editify.umd.js +1 -1
  20. package/lib/index.d.ts +1 -1
  21. package/lib/style.css +1 -1
  22. package/package.json +45 -45
  23. package/src/components/button/button.less +145 -145
  24. package/src/components/button/button.vue +197 -197
  25. package/src/components/button/props.ts +95 -95
  26. package/src/components/checkbox/checkbox.less +84 -84
  27. package/src/components/checkbox/checkbox.vue +68 -68
  28. package/src/components/checkbox/props.ts +49 -49
  29. package/src/components/colors/colors.less +75 -75
  30. package/src/components/colors/colors.vue +36 -36
  31. package/src/components/colors/props.ts +29 -29
  32. package/src/components/icon/icon.less +14 -14
  33. package/src/components/icon/icon.vue +12 -12
  34. package/src/components/icon/props.ts +11 -11
  35. package/src/components/insertImage/insertImage.less +135 -135
  36. package/src/components/insertImage/insertImage.vue +146 -146
  37. package/src/components/insertImage/props.ts +43 -43
  38. package/src/components/insertLink/insertLink.less +64 -64
  39. package/src/components/insertLink/insertLink.vue +58 -58
  40. package/src/components/insertLink/props.ts +16 -16
  41. package/src/components/insertTable/insertTable.less +54 -54
  42. package/src/components/insertTable/insertTable.vue +85 -85
  43. package/src/components/insertTable/props.ts +27 -27
  44. package/src/components/insertVideo/insertVideo.less +135 -135
  45. package/src/components/insertVideo/insertVideo.vue +146 -146
  46. package/src/components/insertVideo/props.ts +43 -43
  47. package/src/components/layer/layer.less +49 -49
  48. package/src/components/layer/layer.vue +598 -598
  49. package/src/components/layer/props.ts +71 -71
  50. package/src/components/menu/menu.less +63 -63
  51. package/src/components/menu/menu.vue +1569 -1569
  52. package/src/components/menu/props.ts +17 -17
  53. package/src/components/toolbar/props.ts +35 -35
  54. package/src/components/toolbar/toolbar.less +89 -89
  55. package/src/components/toolbar/toolbar.vue +1101 -1101
  56. package/src/components/tooltip/props.ts +21 -21
  57. package/src/components/tooltip/tooltip.less +23 -23
  58. package/src/components/tooltip/tooltip.vue +37 -37
  59. package/src/components/triangle/props.ts +26 -26
  60. package/src/components/triangle/triangle.less +79 -79
  61. package/src/components/triangle/triangle.vue +65 -65
  62. package/src/core/function.ts +1144 -1144
  63. package/src/core/rule.ts +259 -259
  64. package/src/core/tool.ts +1137 -1137
  65. package/src/css/base.less +30 -30
  66. package/src/css/hljs.less +54 -54
  67. package/src/editify/editify.less +404 -403
  68. package/src/editify/editify.vue +803 -803
  69. package/src/editify/props.ts +156 -156
  70. package/src/hljs/index.ts +197 -197
  71. package/src/icon/iconfont.css +219 -219
  72. package/src/index.ts +32 -32
  73. package/src/locale/en_US.ts +88 -88
  74. package/src/locale/index.ts +12 -12
  75. package/src/locale/zh_CN.ts +88 -88
  76. package/tsconfig.json +27 -27
  77. package/tsconfig.node.json +11 -11
  78. package/vite-env.d.ts +1 -1
  79. package/vite.config.ts +42 -42
@@ -1,598 +1,598 @@
1
- <template>
2
- <Transition :name="animation ? 'editify-layer-' + animation : 'editify-layer'" @enter="handleEnter" @after-enter="handleAfterEnter" @after-leave="handleAfterLeave">
3
- <div v-if="modelValue" class="editify-layer" :data-editify-placement="realPlacement || null" :style="{ zIndex: zIndex }" ref="elRef">
4
- <Triangle v-if="showTriangle" :color="border && borderColor ? borderColor : background" :background="background" :placement="triPlacement" ref="triangleRef" />
5
- <div ref="wrapRef" class="editify-layer-wrap" :class="{ border: border }" :style="wrapStyle">
6
- <slot></slot>
7
- </div>
8
- </div>
9
- </Transition>
10
- </template>
11
- <script setup lang="ts">
12
- import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
13
- import { element as DapElement, event as DapEvent } from 'dap-util'
14
- import Triangle from '../triangle/triangle.vue'
15
- import { LayerPlacementType, LayerProps } from './props'
16
- import { TrianglePlacementType } from '../triangle/props'
17
- import { ObjectType } from '../../core/tool'
18
-
19
- defineOptions({
20
- name: 'Layer'
21
- })
22
- const instance = getCurrentInstance()!
23
- const props = defineProps(LayerProps)
24
- const emits = defineEmits(['update:modelValue', 'show', 'shown', 'hidden'])
25
-
26
- const realPlacement = ref<LayerPlacementType | null>(null)
27
- const wrapRef = ref<HTMLElement | null>(null)
28
- const elRef = ref<HTMLElement | null>(null)
29
- const triangleRef = ref<InstanceType<typeof Triangle> | null>(null)
30
-
31
- //三角形位置
32
- const triPlacement = computed<TrianglePlacementType>(() => {
33
- if (realPlacement.value == 'bottom-start' || realPlacement.value == 'bottom' || realPlacement.value == 'bottom-end') {
34
- return 'top'
35
- }
36
- if (realPlacement.value == 'top-start' || realPlacement.value == 'top' || realPlacement.value == 'top-end') {
37
- return 'bottom'
38
- }
39
- if (realPlacement.value == 'left-start' || realPlacement.value == 'left' || realPlacement.value == 'left-end') {
40
- return 'right'
41
- }
42
- if (realPlacement.value == 'right-start' || realPlacement.value == 'right' || realPlacement.value == 'right-end') {
43
- return 'left'
44
- }
45
- return 'top'
46
- })
47
- const wrapStyle = computed<ObjectType>(() => {
48
- return {
49
- borderColor: props.border ? props.borderColor || '' : '',
50
- background: props.background || '',
51
- color: props.color || ''
52
- }
53
- })
54
-
55
- //获取目标元素
56
- const getNode = () => {
57
- if (!props.node) {
58
- return null
59
- }
60
- if (DapElement.isElement(props.node)) {
61
- return <HTMLElement>props.node
62
- }
63
- return <HTMLElement>document.body.querySelector(<string>props.node)
64
- }
65
- //根据range设置三角形位置
66
- const setTrianglePositionByRange = () => {
67
- const selection = window.getSelection()
68
- if (selection && selection.rangeCount) {
69
- const range = selection.getRangeAt(0)
70
- const rects = range.getClientRects()
71
- if (rects.length) {
72
- //range的第一个位置
73
- const firstRect = rects[0]
74
- //range的最后一个位置
75
- const lastRect = rects[rects.length - 1]
76
- if (realPlacement.value == 'top') {
77
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
78
- triangleRef.value!.$el.style.right = 'auto'
79
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
80
- triangleRef.value!.$el.style.bottom = 'auto'
81
- } else if (realPlacement.value == 'top-start') {
82
- triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > firstRect.width ? firstRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
83
- triangleRef.value!.$el.style.right = 'auto'
84
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
85
- triangleRef.value!.$el.style.bottom = 'auto'
86
- } else if (realPlacement.value == 'top-end') {
87
- triangleRef.value!.$el.style.left = 'auto'
88
- triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > firstRect.width ? firstRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
89
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
90
- triangleRef.value!.$el.style.bottom = 'auto'
91
- } else if (realPlacement.value == 'bottom') {
92
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
93
- triangleRef.value!.$el.style.right = 'auto'
94
- triangleRef.value!.$el.style.top = 'auto'
95
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
96
- } else if (realPlacement.value == 'bottom-start') {
97
- triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > lastRect.width ? lastRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
98
- triangleRef.value!.$el.style.right = 'auto'
99
- triangleRef.value!.$el.style.top = 'auto'
100
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
101
- } else if (realPlacement.value == 'bottom-end') {
102
- triangleRef.value!.$el.style.left = 'auto'
103
- triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > lastRect.width ? lastRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
104
- triangleRef.value!.$el.style.top = 'auto'
105
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
106
- } else {
107
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
108
- triangleRef.value!.$el.style.right = 'auto'
109
- triangleRef.value!.$el.style.top = -triangleRef.value!.$el.offsetHeight + 1 + 'px'
110
- triangleRef.value!.$el.style.bottom = 'auto'
111
- }
112
- }
113
- }
114
- }
115
- //根据node设置三角形位置
116
- const setTrianglePositionByNode = () => {
117
- const node = getNode()!
118
- if (!DapElement.isElement(node)) {
119
- return
120
- }
121
- if (realPlacement.value == 'top') {
122
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
123
- triangleRef.value!.$el.style.right = 'auto'
124
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
125
- triangleRef.value!.$el.style.bottom = 'auto'
126
- } else if (realPlacement.value == 'top-start') {
127
- triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
128
- triangleRef.value!.$el.style.right = 'auto'
129
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
130
- triangleRef.value!.$el.style.bottom = 'auto'
131
- } else if (realPlacement.value == 'top-end') {
132
- triangleRef.value!.$el.style.left = 'auto'
133
- triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
134
- triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
135
- triangleRef.value!.$el.style.bottom = 'auto'
136
- } else if (realPlacement.value == 'bottom') {
137
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
138
- triangleRef.value!.$el.style.right = 'auto'
139
- triangleRef.value!.$el.style.top = 'auto'
140
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
141
- } else if (realPlacement.value == 'bottom-start') {
142
- triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
143
- triangleRef.value!.$el.style.right = 'auto'
144
- triangleRef.value!.$el.style.top = 'auto'
145
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
146
- } else if (realPlacement.value == 'bottom-end') {
147
- triangleRef.value!.$el.style.left = 'auto'
148
- triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
149
- triangleRef.value!.$el.style.top = 'auto'
150
- triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
151
- } else {
152
- triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
153
- triangleRef.value!.$el.style.right = 'auto'
154
- triangleRef.value!.$el.style.top = -triangleRef.value!.$el.offsetHeight + 1 + 'px'
155
- triangleRef.value!.$el.style.bottom = 'auto'
156
- }
157
- }
158
- //根据range设置位置
159
- const setPositionByRange = () => {
160
- //重置
161
- realPlacement.value = null
162
- const selection = window.getSelection()
163
- if (selection && selection.rangeCount) {
164
- const range = selection.getRangeAt(0)
165
- const rects = range.getClientRects()
166
- if (rects.length) {
167
- //range的第一个位置
168
- const firstRect = rects[0]
169
- //range的最后一个位置
170
- const lastRect = rects[rects.length - 1]
171
- //定位父元素的位置
172
- const parentRect = DapElement.getElementBounding(<HTMLElement>elRef.value!.offsetParent)
173
- //可视窗口高度
174
- const documentHeight = document.documentElement.clientHeight || window.innerHeight
175
- //可视窗口宽度
176
- const documentWidth = document.documentElement.clientWidth || window.innerWidth
177
-
178
- if (props.placement == 'top' || props.placement == 'top-start' || props.placement == 'top-end') {
179
- if (firstRect.top >= 0 && firstRect.top >= parentRect.top && firstRect.top >= elRef.value!.offsetHeight) {
180
- realPlacement.value = props.placement
181
- } else if (documentHeight - lastRect.bottom >= 0 && documentHeight - lastRect.bottom >= parentRect.bottom && documentHeight - lastRect.bottom >= elRef.value!.offsetHeight) {
182
- realPlacement.value = props.placement == 'top' ? 'bottom' : props.placement == 'top-start' ? 'bottom-start' : 'bottom-end'
183
- }
184
- } else if (props.placement == 'bottom' || props.placement == 'bottom-start' || props.placement == 'bottom-end') {
185
- if (documentHeight - lastRect.bottom >= 0 && documentHeight - lastRect.bottom >= parentRect.bottom && documentHeight - lastRect.bottom >= elRef.value!.offsetHeight) {
186
- realPlacement.value = props.placement
187
- } else if (firstRect.top >= 0 && firstRect.top >= parentRect.top && firstRect.top >= elRef.value!.offsetHeight) {
188
- realPlacement.value = props.placement == 'bottom' ? 'top' : props.placement == 'bottom-start' ? 'top-start' : 'top-end'
189
- }
190
- }
191
-
192
- //判断左右是否足够空间显示
193
- if (realPlacement.value == 'top') {
194
- if (documentWidth - firstRect.right + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
195
- realPlacement.value = 'top-end'
196
- } else if (firstRect.left + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
197
- realPlacement.value = 'top-start'
198
- }
199
- } else if (realPlacement.value == 'bottom') {
200
- if (documentWidth - lastRect.right + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
201
- realPlacement.value = 'bottom-end'
202
- } else if (lastRect.left + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
203
- realPlacement.value = 'bottom-start'
204
- }
205
- } else if (realPlacement.value == 'top-start') {
206
- if (documentWidth - firstRect.right + firstRect.width < elRef.value!.offsetWidth) {
207
- if (documentWidth - firstRect.right + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
208
- realPlacement.value = 'top'
209
- } else {
210
- realPlacement.value = 'top-end'
211
- }
212
- }
213
- } else if (realPlacement.value == 'bottom-start') {
214
- if (documentWidth - lastRect.right + lastRect.width < elRef.value!.offsetWidth) {
215
- if (documentWidth - lastRect.right + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
216
- realPlacement.value = 'bottom'
217
- } else {
218
- realPlacement.value = 'bottom-end'
219
- }
220
- }
221
- } else if (realPlacement.value == 'top-end') {
222
- if (firstRect.left + firstRect.width < elRef.value!.offsetWidth) {
223
- if (firstRect.left + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
224
- realPlacement.value = 'top'
225
- } else {
226
- realPlacement.value = 'top-start'
227
- }
228
- }
229
- } else if (realPlacement.value == 'bottom-end') {
230
- if (lastRect.left + lastRect.width < elRef.value!.offsetWidth) {
231
- if (lastRect.left + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
232
- realPlacement.value = 'bottom'
233
- } else {
234
- realPlacement.value = 'bottom-start'
235
- }
236
- }
237
- }
238
- nextTick(() => {
239
- //设置位置对应的样式
240
- if (realPlacement.value == 'top') {
241
- elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
242
- elRef.value!.style.right = 'auto'
243
- elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
244
- elRef.value!.style.bottom = 'auto'
245
- } else if (realPlacement.value == 'top-start') {
246
- elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
247
- elRef.value!.style.right = 'auto'
248
- elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
249
- elRef.value!.style.bottom = 'auto'
250
- } else if (realPlacement.value == 'top-end') {
251
- elRef.value!.style.left = 'auto'
252
- elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
253
- elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
254
- elRef.value!.style.bottom = 'auto'
255
- } else if (realPlacement.value == 'bottom') {
256
- elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
257
- elRef.value!.style.right = 'auto'
258
- elRef.value!.style.top = 'auto'
259
- elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
260
- } else if (realPlacement.value == 'bottom-start') {
261
- elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
262
- elRef.value!.style.right = 'auto'
263
- elRef.value!.style.top = 'auto'
264
- elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
265
- } else if (realPlacement.value == 'bottom-end') {
266
- elRef.value!.style.left = 'auto'
267
- elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
268
- elRef.value!.style.top = 'auto'
269
- elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
270
- } else {
271
- elRef.value!.style.top = 'auto'
272
- elRef.value!.style.bottom = (parentRect.bottom < 0 ? -parentRect.bottom : 0) + 'px'
273
- if (props.placement == 'top') {
274
- //top-end
275
- if (documentWidth - firstRect.right + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
276
- elRef.value!.style.left = 'auto'
277
- elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
278
- }
279
- //top-start
280
- else if (firstRect.left + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
281
- elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
282
- elRef.value!.style.right = 'auto'
283
- }
284
- //top
285
- else {
286
- elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
287
- elRef.value!.style.right = 'auto'
288
- }
289
- } else if (props.placement == 'bottom') {
290
- //bottom-end
291
- if (documentWidth - lastRect.right + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
292
- elRef.value!.style.left = 'auto'
293
- elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
294
- }
295
- //bottom-start
296
- else if (lastRect.left + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
297
- elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
298
- elRef.value!.style.right = 'auto'
299
- }
300
- //bottom
301
- else {
302
- elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
303
- elRef.value!.style.right = 'auto'
304
- }
305
- } else if (props.placement == 'top-start') {
306
- if (documentWidth - firstRect.right + firstRect.width < elRef.value!.offsetWidth) {
307
- //top
308
- if (documentWidth - firstRect.right + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
309
- elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
310
- elRef.value!.style.right = 'auto'
311
- }
312
- //top-end
313
- else {
314
- elRef.value!.style.left = 'auto'
315
- elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
316
- }
317
- }
318
- //top-start
319
- else {
320
- elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
321
- elRef.value!.style.right = 'auto'
322
- }
323
- } else if (props.placement == 'bottom-start') {
324
- if (documentWidth - lastRect.right + lastRect.width < elRef.value!.offsetWidth) {
325
- //bottom
326
- if (documentWidth - lastRect.right + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
327
- elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
328
- elRef.value!.style.right = 'auto'
329
- }
330
- //bottom-end
331
- else {
332
- elRef.value!.style.left = 'auto'
333
- elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
334
- }
335
- }
336
- //bottom-start
337
- else {
338
- elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
339
- elRef.value!.style.right = 'auto'
340
- }
341
- } else if (props.placement == 'top-end') {
342
- if (firstRect.left + firstRect.width < elRef.value!.offsetWidth) {
343
- //top
344
- if (firstRect.left + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
345
- elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
346
- elRef.value!.style.right = 'auto'
347
- }
348
- //top-start
349
- else {
350
- elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
351
- elRef.value!.style.right = 'auto'
352
- }
353
- }
354
- //top-end
355
- else {
356
- elRef.value!.style.left = 'auto'
357
- elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
358
- }
359
- } else if (props.placement == 'bottom-end') {
360
- if (lastRect.left + lastRect.width < elRef.value!.offsetWidth) {
361
- //bottom
362
- if (lastRect.left + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
363
- elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
364
- elRef.value!.style.right = 'auto'
365
- }
366
- //bottom-start
367
- else {
368
- elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
369
- elRef.value!.style.right = 'auto'
370
- }
371
- }
372
- //bottom-end
373
- else {
374
- elRef.value!.style.left = 'auto'
375
- elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
376
- }
377
- }
378
- }
379
- //三角形位置
380
- if (props.showTriangle) {
381
- setTrianglePositionByRange()
382
- }
383
- })
384
- }
385
- }
386
- }
387
- //根据node设置位置
388
- const setPositionByNode = () => {
389
- const node = getNode()!
390
- if (!DapElement.isElement(node)) {
391
- return
392
- }
393
- //重置
394
- realPlacement.value = null
395
- //关联元素位置
396
- const nodeRect = DapElement.getElementBounding(node)
397
- //定位父元素位置
398
- const parentRect = DapElement.getElementBounding(<HTMLElement>elRef.value!.offsetParent)
399
- //设置真实的位置
400
- if (props.placement == 'top' || props.placement == 'top-start' || props.placement == 'top-end') {
401
- if (nodeRect.top >= 0 && nodeRect.top >= parentRect.top && nodeRect.top >= elRef.value!.offsetHeight) {
402
- realPlacement.value = props.placement
403
- } else if (nodeRect.bottom >= 0 && nodeRect.bottom >= parentRect.bottom && nodeRect.bottom >= elRef.value!.offsetHeight) {
404
- realPlacement.value = props.placement == 'top' ? 'bottom' : props.placement == 'top-start' ? 'bottom-start' : 'bottom-end'
405
- }
406
- } else if (props.placement == 'bottom' || props.placement == 'bottom-start' || props.placement == 'bottom-end') {
407
- if (nodeRect.bottom >= 0 && nodeRect.bottom >= parentRect.bottom && nodeRect.bottom >= elRef.value!.offsetHeight) {
408
- realPlacement.value = props.placement
409
- } else if (nodeRect.top >= 0 && nodeRect.top >= parentRect.top && nodeRect.top >= elRef.value!.offsetHeight) {
410
- realPlacement.value = props.placement == 'bottom' ? 'top' : props.placement == 'bottom-start' ? 'top-start' : 'top-end'
411
- }
412
- }
413
- //判断左右是否足够空间显示
414
- if (realPlacement.value == 'top') {
415
- if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
416
- realPlacement.value = 'top-end'
417
- } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
418
- realPlacement.value = 'top-start'
419
- }
420
- } else if (realPlacement.value == 'top-start') {
421
- if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
422
- if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
423
- realPlacement.value = 'top'
424
- } else {
425
- realPlacement.value = 'top-end'
426
- }
427
- }
428
- } else if (realPlacement.value == 'top-end') {
429
- if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
430
- if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
431
- realPlacement.value = 'top'
432
- } else {
433
- realPlacement.value = 'top-start'
434
- }
435
- }
436
- } else if (realPlacement.value == 'bottom') {
437
- if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
438
- realPlacement.value = 'bottom-end'
439
- } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
440
- realPlacement.value = 'bottom-start'
441
- }
442
- } else if (realPlacement.value == 'bottom-start') {
443
- if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
444
- if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
445
- realPlacement.value = 'bottom'
446
- } else {
447
- realPlacement.value = 'bottom-end'
448
- }
449
- }
450
- } else if (realPlacement.value == 'bottom-end') {
451
- if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
452
- if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
453
- realPlacement.value = 'bottom'
454
- } else {
455
- realPlacement.value = 'bottom-start'
456
- }
457
- }
458
- }
459
-
460
- nextTick(() => {
461
- //设置位置对应的样式
462
- if (realPlacement.value == 'top') {
463
- elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
464
- elRef.value!.style.right = 'auto'
465
- elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
466
- elRef.value!.style.bottom = 'auto'
467
- } else if (realPlacement.value == 'top-start') {
468
- elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
469
- elRef.value!.style.right = 'auto'
470
- elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
471
- elRef.value!.style.bottom = 'auto'
472
- } else if (realPlacement.value == 'top-end') {
473
- elRef.value!.style.left = 'auto'
474
- elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
475
- elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
476
- elRef.value!.style.bottom = 'auto'
477
- } else if (realPlacement.value == 'bottom') {
478
- elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
479
- elRef.value!.style.right = 'auto'
480
- elRef.value!.style.top = 'auto'
481
- elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
482
- } else if (realPlacement.value == 'bottom-start') {
483
- elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
484
- elRef.value!.style.right = 'auto'
485
- elRef.value!.style.top = 'auto'
486
- elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
487
- } else if (realPlacement.value == 'bottom-end') {
488
- elRef.value!.style.left = 'auto'
489
- elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
490
- elRef.value!.style.top = 'auto'
491
- elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
492
- } else {
493
- elRef.value!.style.top = 'auto'
494
- elRef.value!.style.bottom = (parentRect.bottom < 0 ? -parentRect.bottom : 0) + 'px'
495
- if (props.placement == 'top' || props.placement == 'bottom') {
496
- if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
497
- elRef.value!.style.left = 'auto'
498
- elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
499
- } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
500
- elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
501
- elRef.value!.style.right = 'auto'
502
- } else {
503
- elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
504
- elRef.value!.style.right = 'auto'
505
- }
506
- } else if (props.placement == 'top-start' || props.placement == 'bottom-start') {
507
- if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
508
- if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
509
- elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
510
- elRef.value!.style.right = 'auto'
511
- } else {
512
- elRef.value!.style.left = 'auto'
513
- elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
514
- }
515
- } else {
516
- elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
517
- elRef.value!.style.right = 'auto'
518
- }
519
- } else if (props.placement == 'top-end' || props.placement == 'bottom-end') {
520
- if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
521
- if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
522
- elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
523
- elRef.value!.style.right = 'auto'
524
- } else {
525
- elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
526
- elRef.value!.style.right = 'auto'
527
- }
528
- } else {
529
- elRef.value!.style.left = 'auto'
530
- elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
531
- }
532
- }
533
- }
534
- //三角形位置
535
- if (props.showTriangle) {
536
- setTrianglePositionByNode()
537
- }
538
- })
539
- }
540
- //设置位置
541
- const setPosition = () => {
542
- //如果根据range来定位
543
- if (props.useRange) {
544
- setPositionByRange()
545
- }
546
- //根据传入的node来定位
547
- else {
548
- setPositionByNode()
549
- }
550
- }
551
- //显示时
552
- const handleEnter = (el: Element) => {
553
- setPosition()
554
- emits('show', el)
555
- }
556
- //完全显示后
557
- const handleAfterEnter = (el: Element) => {
558
- emits('shown', el)
559
- }
560
- //完全隐藏后
561
- const handleAfterLeave = (el: Element) => {
562
- emits('hidden', el)
563
- }
564
- //窗口尺寸改动
565
- const handleResize = () => {
566
- if (props.modelValue) {
567
- emits('update:modelValue', false)
568
- }
569
- }
570
- //点击定位父元素外的元素关闭浮层
571
- const handleClick = (e: Event) => {
572
- if (!DapElement.isElement(elRef.value)) {
573
- return
574
- }
575
- if (DapElement.isContains(<HTMLElement>elRef.value!.offsetParent, <HTMLElement>e.target)) {
576
- return
577
- }
578
- if (props.modelValue) {
579
- emits('update:modelValue', false)
580
- }
581
- }
582
-
583
- onMounted(() => {
584
- if (props.modelValue) {
585
- setPosition()
586
- }
587
- DapEvent.on(window, `click.editify_layer_${instance.uid}`, handleClick)
588
- DapEvent.on(window, `resize.editify_layer_${instance.uid}`, handleResize)
589
- })
590
- onBeforeUnmount(() => {
591
- DapEvent.off(window, `click.editify_layer_${instance.uid} resize.editify_layer_${instance.uid}`)
592
- })
593
-
594
- defineExpose({
595
- setPosition
596
- })
597
- </script>
598
- <style scoped src="./layer.less"></style>
1
+ <template>
2
+ <Transition :name="animation ? 'editify-layer-' + animation : 'editify-layer'" @enter="handleEnter" @after-enter="handleAfterEnter" @after-leave="handleAfterLeave">
3
+ <div v-if="modelValue" class="editify-layer" :data-editify-placement="realPlacement || null" :style="{ zIndex: zIndex }" ref="elRef">
4
+ <Triangle v-if="showTriangle" :color="border && borderColor ? borderColor : background" :background="background" :placement="triPlacement" ref="triangleRef" />
5
+ <div ref="wrapRef" class="editify-layer-wrap" :class="{ border: border }" :style="wrapStyle">
6
+ <slot></slot>
7
+ </div>
8
+ </div>
9
+ </Transition>
10
+ </template>
11
+ <script setup lang="ts">
12
+ import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
13
+ import { element as DapElement, event as DapEvent } from 'dap-util'
14
+ import Triangle from '../triangle/triangle.vue'
15
+ import { LayerPlacementType, LayerProps } from './props'
16
+ import { TrianglePlacementType } from '../triangle/props'
17
+ import { ObjectType } from '../../core/tool'
18
+
19
+ defineOptions({
20
+ name: 'Layer'
21
+ })
22
+ const instance = getCurrentInstance()!
23
+ const props = defineProps(LayerProps)
24
+ const emits = defineEmits(['update:modelValue', 'show', 'shown', 'hidden'])
25
+
26
+ const realPlacement = ref<LayerPlacementType | null>(null)
27
+ const wrapRef = ref<HTMLElement | null>(null)
28
+ const elRef = ref<HTMLElement | null>(null)
29
+ const triangleRef = ref<InstanceType<typeof Triangle> | null>(null)
30
+
31
+ //三角形位置
32
+ const triPlacement = computed<TrianglePlacementType>(() => {
33
+ if (realPlacement.value == 'bottom-start' || realPlacement.value == 'bottom' || realPlacement.value == 'bottom-end') {
34
+ return 'top'
35
+ }
36
+ if (realPlacement.value == 'top-start' || realPlacement.value == 'top' || realPlacement.value == 'top-end') {
37
+ return 'bottom'
38
+ }
39
+ if (realPlacement.value == 'left-start' || realPlacement.value == 'left' || realPlacement.value == 'left-end') {
40
+ return 'right'
41
+ }
42
+ if (realPlacement.value == 'right-start' || realPlacement.value == 'right' || realPlacement.value == 'right-end') {
43
+ return 'left'
44
+ }
45
+ return 'top'
46
+ })
47
+ const wrapStyle = computed<ObjectType>(() => {
48
+ return {
49
+ borderColor: props.border ? props.borderColor || '' : '',
50
+ background: props.background || '',
51
+ color: props.color || ''
52
+ }
53
+ })
54
+
55
+ //获取目标元素
56
+ const getNode = () => {
57
+ if (!props.node) {
58
+ return null
59
+ }
60
+ if (DapElement.isElement(props.node)) {
61
+ return <HTMLElement>props.node
62
+ }
63
+ return <HTMLElement>document.body.querySelector(<string>props.node)
64
+ }
65
+ //根据range设置三角形位置
66
+ const setTrianglePositionByRange = () => {
67
+ const selection = window.getSelection()
68
+ if (selection && selection.rangeCount) {
69
+ const range = selection.getRangeAt(0)
70
+ const rects = range.getClientRects()
71
+ if (rects.length) {
72
+ //range的第一个位置
73
+ const firstRect = rects[0]
74
+ //range的最后一个位置
75
+ const lastRect = rects[rects.length - 1]
76
+ if (realPlacement.value == 'top') {
77
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
78
+ triangleRef.value!.$el.style.right = 'auto'
79
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
80
+ triangleRef.value!.$el.style.bottom = 'auto'
81
+ } else if (realPlacement.value == 'top-start') {
82
+ triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > firstRect.width ? firstRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
83
+ triangleRef.value!.$el.style.right = 'auto'
84
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
85
+ triangleRef.value!.$el.style.bottom = 'auto'
86
+ } else if (realPlacement.value == 'top-end') {
87
+ triangleRef.value!.$el.style.left = 'auto'
88
+ triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > firstRect.width ? firstRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
89
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
90
+ triangleRef.value!.$el.style.bottom = 'auto'
91
+ } else if (realPlacement.value == 'bottom') {
92
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
93
+ triangleRef.value!.$el.style.right = 'auto'
94
+ triangleRef.value!.$el.style.top = 'auto'
95
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
96
+ } else if (realPlacement.value == 'bottom-start') {
97
+ triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > lastRect.width ? lastRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
98
+ triangleRef.value!.$el.style.right = 'auto'
99
+ triangleRef.value!.$el.style.top = 'auto'
100
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
101
+ } else if (realPlacement.value == 'bottom-end') {
102
+ triangleRef.value!.$el.style.left = 'auto'
103
+ triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > lastRect.width ? lastRect.width : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
104
+ triangleRef.value!.$el.style.top = 'auto'
105
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
106
+ } else {
107
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
108
+ triangleRef.value!.$el.style.right = 'auto'
109
+ triangleRef.value!.$el.style.top = -triangleRef.value!.$el.offsetHeight + 1 + 'px'
110
+ triangleRef.value!.$el.style.bottom = 'auto'
111
+ }
112
+ }
113
+ }
114
+ }
115
+ //根据node设置三角形位置
116
+ const setTrianglePositionByNode = () => {
117
+ const node = getNode()!
118
+ if (!DapElement.isElement(node)) {
119
+ return
120
+ }
121
+ if (realPlacement.value == 'top') {
122
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
123
+ triangleRef.value!.$el.style.right = 'auto'
124
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
125
+ triangleRef.value!.$el.style.bottom = 'auto'
126
+ } else if (realPlacement.value == 'top-start') {
127
+ triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
128
+ triangleRef.value!.$el.style.right = 'auto'
129
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
130
+ triangleRef.value!.$el.style.bottom = 'auto'
131
+ } else if (realPlacement.value == 'top-end') {
132
+ triangleRef.value!.$el.style.left = 'auto'
133
+ triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
134
+ triangleRef.value!.$el.style.top = wrapRef.value!.offsetHeight - 1 + 'px'
135
+ triangleRef.value!.$el.style.bottom = 'auto'
136
+ } else if (realPlacement.value == 'bottom') {
137
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
138
+ triangleRef.value!.$el.style.right = 'auto'
139
+ triangleRef.value!.$el.style.top = 'auto'
140
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
141
+ } else if (realPlacement.value == 'bottom-start') {
142
+ triangleRef.value!.$el.style.left = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
143
+ triangleRef.value!.$el.style.right = 'auto'
144
+ triangleRef.value!.$el.style.top = 'auto'
145
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
146
+ } else if (realPlacement.value == 'bottom-end') {
147
+ triangleRef.value!.$el.style.left = 'auto'
148
+ triangleRef.value!.$el.style.right = (wrapRef.value!.offsetWidth > node.offsetWidth ? node.offsetWidth : wrapRef.value!.offsetWidth) / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
149
+ triangleRef.value!.$el.style.top = 'auto'
150
+ triangleRef.value!.$el.style.bottom = wrapRef.value!.offsetHeight - 1 + 'px'
151
+ } else {
152
+ triangleRef.value!.$el.style.left = wrapRef.value!.offsetWidth / 2 - triangleRef.value!.$el.offsetWidth / 2 + 'px'
153
+ triangleRef.value!.$el.style.right = 'auto'
154
+ triangleRef.value!.$el.style.top = -triangleRef.value!.$el.offsetHeight + 1 + 'px'
155
+ triangleRef.value!.$el.style.bottom = 'auto'
156
+ }
157
+ }
158
+ //根据range设置位置
159
+ const setPositionByRange = () => {
160
+ //重置
161
+ realPlacement.value = null
162
+ const selection = window.getSelection()
163
+ if (selection && selection.rangeCount) {
164
+ const range = selection.getRangeAt(0)
165
+ const rects = range.getClientRects()
166
+ if (rects.length) {
167
+ //range的第一个位置
168
+ const firstRect = rects[0]
169
+ //range的最后一个位置
170
+ const lastRect = rects[rects.length - 1]
171
+ //定位父元素的位置
172
+ const parentRect = DapElement.getElementBounding(<HTMLElement>elRef.value!.offsetParent)
173
+ //可视窗口高度
174
+ const documentHeight = document.documentElement.clientHeight || window.innerHeight
175
+ //可视窗口宽度
176
+ const documentWidth = document.documentElement.clientWidth || window.innerWidth
177
+
178
+ if (props.placement == 'top' || props.placement == 'top-start' || props.placement == 'top-end') {
179
+ if (firstRect.top >= 0 && firstRect.top >= parentRect.top && firstRect.top >= elRef.value!.offsetHeight) {
180
+ realPlacement.value = props.placement
181
+ } else if (documentHeight - lastRect.bottom >= 0 && documentHeight - lastRect.bottom >= parentRect.bottom && documentHeight - lastRect.bottom >= elRef.value!.offsetHeight) {
182
+ realPlacement.value = props.placement == 'top' ? 'bottom' : props.placement == 'top-start' ? 'bottom-start' : 'bottom-end'
183
+ }
184
+ } else if (props.placement == 'bottom' || props.placement == 'bottom-start' || props.placement == 'bottom-end') {
185
+ if (documentHeight - lastRect.bottom >= 0 && documentHeight - lastRect.bottom >= parentRect.bottom && documentHeight - lastRect.bottom >= elRef.value!.offsetHeight) {
186
+ realPlacement.value = props.placement
187
+ } else if (firstRect.top >= 0 && firstRect.top >= parentRect.top && firstRect.top >= elRef.value!.offsetHeight) {
188
+ realPlacement.value = props.placement == 'bottom' ? 'top' : props.placement == 'bottom-start' ? 'top-start' : 'top-end'
189
+ }
190
+ }
191
+
192
+ //判断左右是否足够空间显示
193
+ if (realPlacement.value == 'top') {
194
+ if (documentWidth - firstRect.right + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
195
+ realPlacement.value = 'top-end'
196
+ } else if (firstRect.left + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
197
+ realPlacement.value = 'top-start'
198
+ }
199
+ } else if (realPlacement.value == 'bottom') {
200
+ if (documentWidth - lastRect.right + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
201
+ realPlacement.value = 'bottom-end'
202
+ } else if (lastRect.left + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
203
+ realPlacement.value = 'bottom-start'
204
+ }
205
+ } else if (realPlacement.value == 'top-start') {
206
+ if (documentWidth - firstRect.right + firstRect.width < elRef.value!.offsetWidth) {
207
+ if (documentWidth - firstRect.right + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
208
+ realPlacement.value = 'top'
209
+ } else {
210
+ realPlacement.value = 'top-end'
211
+ }
212
+ }
213
+ } else if (realPlacement.value == 'bottom-start') {
214
+ if (documentWidth - lastRect.right + lastRect.width < elRef.value!.offsetWidth) {
215
+ if (documentWidth - lastRect.right + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
216
+ realPlacement.value = 'bottom'
217
+ } else {
218
+ realPlacement.value = 'bottom-end'
219
+ }
220
+ }
221
+ } else if (realPlacement.value == 'top-end') {
222
+ if (firstRect.left + firstRect.width < elRef.value!.offsetWidth) {
223
+ if (firstRect.left + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
224
+ realPlacement.value = 'top'
225
+ } else {
226
+ realPlacement.value = 'top-start'
227
+ }
228
+ }
229
+ } else if (realPlacement.value == 'bottom-end') {
230
+ if (lastRect.left + lastRect.width < elRef.value!.offsetWidth) {
231
+ if (lastRect.left + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
232
+ realPlacement.value = 'bottom'
233
+ } else {
234
+ realPlacement.value = 'bottom-start'
235
+ }
236
+ }
237
+ }
238
+ nextTick(() => {
239
+ //设置位置对应的样式
240
+ if (realPlacement.value == 'top') {
241
+ elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
242
+ elRef.value!.style.right = 'auto'
243
+ elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
244
+ elRef.value!.style.bottom = 'auto'
245
+ } else if (realPlacement.value == 'top-start') {
246
+ elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
247
+ elRef.value!.style.right = 'auto'
248
+ elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
249
+ elRef.value!.style.bottom = 'auto'
250
+ } else if (realPlacement.value == 'top-end') {
251
+ elRef.value!.style.left = 'auto'
252
+ elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
253
+ elRef.value!.style.top = firstRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
254
+ elRef.value!.style.bottom = 'auto'
255
+ } else if (realPlacement.value == 'bottom') {
256
+ elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
257
+ elRef.value!.style.right = 'auto'
258
+ elRef.value!.style.top = 'auto'
259
+ elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
260
+ } else if (realPlacement.value == 'bottom-start') {
261
+ elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
262
+ elRef.value!.style.right = 'auto'
263
+ elRef.value!.style.top = 'auto'
264
+ elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
265
+ } else if (realPlacement.value == 'bottom-end') {
266
+ elRef.value!.style.left = 'auto'
267
+ elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
268
+ elRef.value!.style.top = 'auto'
269
+ elRef.value!.style.bottom = documentHeight - lastRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
270
+ } else {
271
+ elRef.value!.style.top = 'auto'
272
+ elRef.value!.style.bottom = (parentRect.bottom < 0 ? -parentRect.bottom : 0) + 'px'
273
+ if (props.placement == 'top') {
274
+ //top-end
275
+ if (documentWidth - firstRect.right + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
276
+ elRef.value!.style.left = 'auto'
277
+ elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
278
+ }
279
+ //top-start
280
+ else if (firstRect.left + firstRect.width / 2 < elRef.value!.offsetWidth / 2) {
281
+ elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
282
+ elRef.value!.style.right = 'auto'
283
+ }
284
+ //top
285
+ else {
286
+ elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
287
+ elRef.value!.style.right = 'auto'
288
+ }
289
+ } else if (props.placement == 'bottom') {
290
+ //bottom-end
291
+ if (documentWidth - lastRect.right + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
292
+ elRef.value!.style.left = 'auto'
293
+ elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
294
+ }
295
+ //bottom-start
296
+ else if (lastRect.left + lastRect.width / 2 < elRef.value!.offsetWidth / 2) {
297
+ elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
298
+ elRef.value!.style.right = 'auto'
299
+ }
300
+ //bottom
301
+ else {
302
+ elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
303
+ elRef.value!.style.right = 'auto'
304
+ }
305
+ } else if (props.placement == 'top-start') {
306
+ if (documentWidth - firstRect.right + firstRect.width < elRef.value!.offsetWidth) {
307
+ //top
308
+ if (documentWidth - firstRect.right + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
309
+ elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
310
+ elRef.value!.style.right = 'auto'
311
+ }
312
+ //top-end
313
+ else {
314
+ elRef.value!.style.left = 'auto'
315
+ elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
316
+ }
317
+ }
318
+ //top-start
319
+ else {
320
+ elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
321
+ elRef.value!.style.right = 'auto'
322
+ }
323
+ } else if (props.placement == 'bottom-start') {
324
+ if (documentWidth - lastRect.right + lastRect.width < elRef.value!.offsetWidth) {
325
+ //bottom
326
+ if (documentWidth - lastRect.right + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
327
+ elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
328
+ elRef.value!.style.right = 'auto'
329
+ }
330
+ //bottom-end
331
+ else {
332
+ elRef.value!.style.left = 'auto'
333
+ elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
334
+ }
335
+ }
336
+ //bottom-start
337
+ else {
338
+ elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
339
+ elRef.value!.style.right = 'auto'
340
+ }
341
+ } else if (props.placement == 'top-end') {
342
+ if (firstRect.left + firstRect.width < elRef.value!.offsetWidth) {
343
+ //top
344
+ if (firstRect.left + firstRect.width / 2 >= elRef.value!.offsetWidth / 2) {
345
+ elRef.value!.style.left = firstRect.left - parentRect.left + firstRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
346
+ elRef.value!.style.right = 'auto'
347
+ }
348
+ //top-start
349
+ else {
350
+ elRef.value!.style.left = firstRect.left - parentRect.left + 'px'
351
+ elRef.value!.style.right = 'auto'
352
+ }
353
+ }
354
+ //top-end
355
+ else {
356
+ elRef.value!.style.left = 'auto'
357
+ elRef.value!.style.right = documentWidth - firstRect.right - parentRect.right + 'px'
358
+ }
359
+ } else if (props.placement == 'bottom-end') {
360
+ if (lastRect.left + lastRect.width < elRef.value!.offsetWidth) {
361
+ //bottom
362
+ if (lastRect.left + lastRect.width / 2 >= elRef.value!.offsetWidth / 2) {
363
+ elRef.value!.style.left = lastRect.left - parentRect.left + lastRect.width / 2 - elRef.value!.offsetWidth / 2 + 'px'
364
+ elRef.value!.style.right = 'auto'
365
+ }
366
+ //bottom-start
367
+ else {
368
+ elRef.value!.style.left = lastRect.left - parentRect.left + 'px'
369
+ elRef.value!.style.right = 'auto'
370
+ }
371
+ }
372
+ //bottom-end
373
+ else {
374
+ elRef.value!.style.left = 'auto'
375
+ elRef.value!.style.right = documentWidth - lastRect.right - parentRect.right + 'px'
376
+ }
377
+ }
378
+ }
379
+ //三角形位置
380
+ if (props.showTriangle) {
381
+ setTrianglePositionByRange()
382
+ }
383
+ })
384
+ }
385
+ }
386
+ }
387
+ //根据node设置位置
388
+ const setPositionByNode = () => {
389
+ const node = getNode()!
390
+ if (!DapElement.isElement(node)) {
391
+ return
392
+ }
393
+ //重置
394
+ realPlacement.value = null
395
+ //关联元素位置
396
+ const nodeRect = DapElement.getElementBounding(node)
397
+ //定位父元素位置
398
+ const parentRect = DapElement.getElementBounding(<HTMLElement>elRef.value!.offsetParent)
399
+ //设置真实的位置
400
+ if (props.placement == 'top' || props.placement == 'top-start' || props.placement == 'top-end') {
401
+ if (nodeRect.top >= 0 && nodeRect.top >= parentRect.top && nodeRect.top >= elRef.value!.offsetHeight) {
402
+ realPlacement.value = props.placement
403
+ } else if (nodeRect.bottom >= 0 && nodeRect.bottom >= parentRect.bottom && nodeRect.bottom >= elRef.value!.offsetHeight) {
404
+ realPlacement.value = props.placement == 'top' ? 'bottom' : props.placement == 'top-start' ? 'bottom-start' : 'bottom-end'
405
+ }
406
+ } else if (props.placement == 'bottom' || props.placement == 'bottom-start' || props.placement == 'bottom-end') {
407
+ if (nodeRect.bottom >= 0 && nodeRect.bottom >= parentRect.bottom && nodeRect.bottom >= elRef.value!.offsetHeight) {
408
+ realPlacement.value = props.placement
409
+ } else if (nodeRect.top >= 0 && nodeRect.top >= parentRect.top && nodeRect.top >= elRef.value!.offsetHeight) {
410
+ realPlacement.value = props.placement == 'bottom' ? 'top' : props.placement == 'bottom-start' ? 'top-start' : 'top-end'
411
+ }
412
+ }
413
+ //判断左右是否足够空间显示
414
+ if (realPlacement.value == 'top') {
415
+ if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
416
+ realPlacement.value = 'top-end'
417
+ } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
418
+ realPlacement.value = 'top-start'
419
+ }
420
+ } else if (realPlacement.value == 'top-start') {
421
+ if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
422
+ if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
423
+ realPlacement.value = 'top'
424
+ } else {
425
+ realPlacement.value = 'top-end'
426
+ }
427
+ }
428
+ } else if (realPlacement.value == 'top-end') {
429
+ if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
430
+ if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
431
+ realPlacement.value = 'top'
432
+ } else {
433
+ realPlacement.value = 'top-start'
434
+ }
435
+ }
436
+ } else if (realPlacement.value == 'bottom') {
437
+ if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
438
+ realPlacement.value = 'bottom-end'
439
+ } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
440
+ realPlacement.value = 'bottom-start'
441
+ }
442
+ } else if (realPlacement.value == 'bottom-start') {
443
+ if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
444
+ if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
445
+ realPlacement.value = 'bottom'
446
+ } else {
447
+ realPlacement.value = 'bottom-end'
448
+ }
449
+ }
450
+ } else if (realPlacement.value == 'bottom-end') {
451
+ if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
452
+ if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
453
+ realPlacement.value = 'bottom'
454
+ } else {
455
+ realPlacement.value = 'bottom-start'
456
+ }
457
+ }
458
+ }
459
+
460
+ nextTick(() => {
461
+ //设置位置对应的样式
462
+ if (realPlacement.value == 'top') {
463
+ elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
464
+ elRef.value!.style.right = 'auto'
465
+ elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
466
+ elRef.value!.style.bottom = 'auto'
467
+ } else if (realPlacement.value == 'top-start') {
468
+ elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
469
+ elRef.value!.style.right = 'auto'
470
+ elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
471
+ elRef.value!.style.bottom = 'auto'
472
+ } else if (realPlacement.value == 'top-end') {
473
+ elRef.value!.style.left = 'auto'
474
+ elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
475
+ elRef.value!.style.top = nodeRect.top - parentRect.top - elRef.value!.offsetHeight + 'px'
476
+ elRef.value!.style.bottom = 'auto'
477
+ } else if (realPlacement.value == 'bottom') {
478
+ elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
479
+ elRef.value!.style.right = 'auto'
480
+ elRef.value!.style.top = 'auto'
481
+ elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
482
+ } else if (realPlacement.value == 'bottom-start') {
483
+ elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
484
+ elRef.value!.style.right = 'auto'
485
+ elRef.value!.style.top = 'auto'
486
+ elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
487
+ } else if (realPlacement.value == 'bottom-end') {
488
+ elRef.value!.style.left = 'auto'
489
+ elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
490
+ elRef.value!.style.top = 'auto'
491
+ elRef.value!.style.bottom = nodeRect.bottom - parentRect.bottom - elRef.value!.offsetHeight + 'px'
492
+ } else {
493
+ elRef.value!.style.top = 'auto'
494
+ elRef.value!.style.bottom = (parentRect.bottom < 0 ? -parentRect.bottom : 0) + 'px'
495
+ if (props.placement == 'top' || props.placement == 'bottom') {
496
+ if (nodeRect.right + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
497
+ elRef.value!.style.left = 'auto'
498
+ elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
499
+ } else if (nodeRect.left + node.offsetWidth / 2 < elRef.value!.offsetWidth / 2) {
500
+ elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
501
+ elRef.value!.style.right = 'auto'
502
+ } else {
503
+ elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
504
+ elRef.value!.style.right = 'auto'
505
+ }
506
+ } else if (props.placement == 'top-start' || props.placement == 'bottom-start') {
507
+ if (nodeRect.right + node.offsetWidth < elRef.value!.offsetWidth) {
508
+ if (nodeRect.right + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
509
+ elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
510
+ elRef.value!.style.right = 'auto'
511
+ } else {
512
+ elRef.value!.style.left = 'auto'
513
+ elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
514
+ }
515
+ } else {
516
+ elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
517
+ elRef.value!.style.right = 'auto'
518
+ }
519
+ } else if (props.placement == 'top-end' || props.placement == 'bottom-end') {
520
+ if (nodeRect.left + node.offsetWidth < elRef.value!.offsetWidth) {
521
+ if (nodeRect.left + node.offsetWidth / 2 >= elRef.value!.offsetWidth / 2) {
522
+ elRef.value!.style.left = nodeRect.left - parentRect.left + node.offsetWidth / 2 - elRef.value!.offsetWidth / 2 + 'px'
523
+ elRef.value!.style.right = 'auto'
524
+ } else {
525
+ elRef.value!.style.left = nodeRect.left - parentRect.left + 'px'
526
+ elRef.value!.style.right = 'auto'
527
+ }
528
+ } else {
529
+ elRef.value!.style.left = 'auto'
530
+ elRef.value!.style.right = nodeRect.right - parentRect.right + 'px'
531
+ }
532
+ }
533
+ }
534
+ //三角形位置
535
+ if (props.showTriangle) {
536
+ setTrianglePositionByNode()
537
+ }
538
+ })
539
+ }
540
+ //设置位置
541
+ const setPosition = () => {
542
+ //如果根据range来定位
543
+ if (props.useRange) {
544
+ setPositionByRange()
545
+ }
546
+ //根据传入的node来定位
547
+ else {
548
+ setPositionByNode()
549
+ }
550
+ }
551
+ //显示时
552
+ const handleEnter = (el: Element) => {
553
+ setPosition()
554
+ emits('show', el)
555
+ }
556
+ //完全显示后
557
+ const handleAfterEnter = (el: Element) => {
558
+ emits('shown', el)
559
+ }
560
+ //完全隐藏后
561
+ const handleAfterLeave = (el: Element) => {
562
+ emits('hidden', el)
563
+ }
564
+ //窗口尺寸改动
565
+ const handleResize = () => {
566
+ if (props.modelValue) {
567
+ emits('update:modelValue', false)
568
+ }
569
+ }
570
+ //点击定位父元素外的元素关闭浮层
571
+ const handleClick = (e: Event) => {
572
+ if (!DapElement.isElement(elRef.value)) {
573
+ return
574
+ }
575
+ if (DapElement.isContains(<HTMLElement>elRef.value!.offsetParent, <HTMLElement>e.target)) {
576
+ return
577
+ }
578
+ if (props.modelValue) {
579
+ emits('update:modelValue', false)
580
+ }
581
+ }
582
+
583
+ onMounted(() => {
584
+ if (props.modelValue) {
585
+ setPosition()
586
+ }
587
+ DapEvent.on(window, `click.editify_layer_${instance.uid}`, handleClick)
588
+ DapEvent.on(window, `resize.editify_layer_${instance.uid}`, handleResize)
589
+ })
590
+ onBeforeUnmount(() => {
591
+ DapEvent.off(window, `click.editify_layer_${instance.uid} resize.editify_layer_${instance.uid}`)
592
+ })
593
+
594
+ defineExpose({
595
+ setPosition
596
+ })
597
+ </script>
598
+ <style scoped src="./layer.less"></style>