vue-editify 0.1.10 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. package/examples/App.vue +21 -96
  2. package/examples/main.ts +4 -0
  3. package/lib/components/button/button.vue.d.ts +143 -0
  4. package/lib/components/button/props.d.ts +73 -0
  5. package/lib/components/checkbox/checkbox.vue.d.ts +80 -0
  6. package/lib/components/checkbox/props.d.ts +36 -0
  7. package/lib/components/colors/colors.vue.d.ts +47 -0
  8. package/lib/components/colors/props.d.ts +22 -0
  9. package/lib/components/icon/icon.vue.d.ts +14 -0
  10. package/lib/components/icon/props.d.ts +9 -0
  11. package/lib/components/insertImage/insertImage.vue.d.ts +74 -0
  12. package/lib/components/insertImage/props.d.ts +34 -0
  13. package/lib/components/insertLink/insertLink.vue.d.ts +27 -0
  14. package/lib/components/insertLink/props.d.ts +13 -0
  15. package/lib/components/insertTable/insertTable.vue.d.ts +36 -0
  16. package/lib/components/insertTable/props.d.ts +22 -0
  17. package/lib/components/insertVideo/insertVideo.vue.d.ts +74 -0
  18. package/lib/components/insertVideo/props.d.ts +34 -0
  19. package/lib/components/layer/layer.vue.d.ts +129 -0
  20. package/lib/components/layer/props.d.ts +53 -0
  21. package/lib/components/menu/menu.vue.d.ts +25 -0
  22. package/lib/components/menu/props.d.ts +14 -0
  23. package/lib/components/toolbar/props.d.ts +27 -0
  24. package/lib/components/toolbar/toolbar.vue.d.ts +56 -0
  25. package/lib/components/tooltip/props.d.ts +17 -0
  26. package/lib/components/tooltip/tooltip.vue.d.ts +39 -0
  27. package/lib/components/triangle/props.d.ts +19 -0
  28. package/lib/components/triangle/triangle.vue.d.ts +34 -0
  29. package/lib/core/function.d.ts +45 -0
  30. package/lib/core/rule.d.ts +9 -0
  31. package/lib/core/tool.d.ts +185 -0
  32. package/lib/editify/editify.vue.d.ts +676 -0
  33. package/lib/editify/props.d.ts +110 -0
  34. package/lib/editify.es.js +5706 -5727
  35. package/lib/editify.umd.js +1 -1
  36. package/lib/hljs/index.d.ts +7 -0
  37. package/lib/index.d.ts +17 -0
  38. package/lib/locale/en_US.d.ts +3 -0
  39. package/lib/locale/index.d.ts +2 -0
  40. package/lib/locale/zh_CN.d.ts +3 -0
  41. package/lib/style.css +1 -1
  42. package/package.json +16 -8
  43. package/src/components/button/button.less +145 -0
  44. package/src/components/button/button.vue +197 -0
  45. package/src/components/button/props.ts +95 -0
  46. package/src/components/checkbox/checkbox.less +84 -0
  47. package/src/components/checkbox/checkbox.vue +68 -0
  48. package/src/components/checkbox/props.ts +49 -0
  49. package/src/components/colors/colors.less +75 -0
  50. package/src/components/colors/colors.vue +36 -0
  51. package/src/components/colors/props.ts +29 -0
  52. package/src/components/{base/Icon.vue → icon/icon.less} +0 -17
  53. package/src/components/icon/icon.vue +12 -0
  54. package/src/components/icon/props.ts +11 -0
  55. package/src/components/insertImage/insertImage.less +135 -0
  56. package/src/components/insertImage/insertImage.vue +146 -0
  57. package/src/components/insertImage/props.ts +43 -0
  58. package/src/components/insertLink/insertLink.less +64 -0
  59. package/src/components/insertLink/insertLink.vue +58 -0
  60. package/src/components/insertLink/props.ts +16 -0
  61. package/src/components/insertTable/insertTable.less +54 -0
  62. package/src/components/insertTable/insertTable.vue +85 -0
  63. package/src/components/insertTable/props.ts +27 -0
  64. package/src/components/insertVideo/insertVideo.less +135 -0
  65. package/src/components/insertVideo/insertVideo.vue +146 -0
  66. package/src/components/insertVideo/props.ts +43 -0
  67. package/src/components/layer/layer.less +49 -0
  68. package/src/components/layer/layer.vue +598 -0
  69. package/src/components/layer/props.ts +71 -0
  70. package/src/components/menu/menu.less +64 -0
  71. package/src/components/menu/menu.vue +1570 -0
  72. package/src/components/menu/props.ts +17 -0
  73. package/src/components/toolbar/props.ts +35 -0
  74. package/src/components/toolbar/toolbar.less +89 -0
  75. package/src/components/toolbar/toolbar.vue +1101 -0
  76. package/src/components/tooltip/props.ts +21 -0
  77. package/src/components/tooltip/tooltip.less +23 -0
  78. package/src/components/tooltip/tooltip.vue +37 -0
  79. package/src/components/triangle/props.ts +26 -0
  80. package/src/components/triangle/triangle.less +79 -0
  81. package/src/components/triangle/triangle.vue +65 -0
  82. package/src/core/function.ts +1144 -0
  83. package/src/core/{rule.js → rule.ts} +33 -33
  84. package/src/core/{tool.js → tool.ts} +221 -145
  85. package/src/editify/editify.less +404 -0
  86. package/src/editify/editify.vue +805 -0
  87. package/src/editify/props.ts +141 -0
  88. package/src/hljs/{index.js → index.ts} +7 -4
  89. package/src/index.ts +32 -0
  90. package/src/locale/{en_US.js → en_US.ts} +3 -1
  91. package/src/locale/index.ts +12 -0
  92. package/src/locale/{zh_CN.js → zh_CN.ts} +3 -1
  93. package/tsconfig.json +27 -0
  94. package/tsconfig.node.json +11 -0
  95. package/vite-env.d.ts +1 -0
  96. package/vite.config.ts +39 -0
  97. package/examples/main.js +0 -4
  98. package/src/Editify.vue +0 -1184
  99. package/src/components/Menu.vue +0 -1623
  100. package/src/components/Toolbar.vue +0 -1215
  101. package/src/components/base/Button.vue +0 -450
  102. package/src/components/base/Checkbox.vue +0 -196
  103. package/src/components/base/Layer.vue +0 -713
  104. package/src/components/base/Tooltip.vue +0 -82
  105. package/src/components/base/Triangle.vue +0 -159
  106. package/src/components/common/Colors.vue +0 -138
  107. package/src/components/common/InsertImage.vue +0 -316
  108. package/src/components/common/InsertLink.vue +0 -136
  109. package/src/components/common/InsertTable.vue +0 -157
  110. package/src/components/common/InsertVideo.vue +0 -316
  111. package/src/core/function.js +0 -1044
  112. package/src/index.js +0 -24
  113. package/src/locale/index.js +0 -14
@@ -0,0 +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>
@@ -0,0 +1,71 @@
1
+ import { ExtractPublicPropTypes, PropType } from 'vue'
2
+
3
+ export type LayerPlacementType = 'top' | 'bottom' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end'
4
+
5
+ export type LayerAnimationType = 'translate' | 'fade' | null
6
+
7
+ export const LayerProps = {
8
+ //是否显示
9
+ modelValue: {
10
+ type: Boolean,
11
+ default: false
12
+ },
13
+ //关联元素
14
+ node: {
15
+ type: [String, HTMLElement] as PropType<string | HTMLElement | null>,
16
+ default: null
17
+ },
18
+ //是否显示边框
19
+ border: {
20
+ type: Boolean,
21
+ default: false
22
+ },
23
+ //边框颜色
24
+ borderColor: {
25
+ type: String,
26
+ default: null
27
+ },
28
+ //背景色
29
+ background: {
30
+ type: String,
31
+ default: null
32
+ },
33
+ //字体颜色
34
+ color: {
35
+ type: String,
36
+ default: null
37
+ },
38
+ //位置
39
+ placement: {
40
+ type: String as PropType<LayerPlacementType>,
41
+ default: 'bottom',
42
+ validator(value: any) {
43
+ return ['top', 'bottom', 'top-start', 'top-end', 'bottom-start', 'bottom-end'].includes(value)
44
+ }
45
+ },
46
+ //是否显示三角形
47
+ showTriangle: {
48
+ type: Boolean,
49
+ default: false
50
+ },
51
+ //层级
52
+ zIndex: {
53
+ type: Number,
54
+ default: 10
55
+ },
56
+ //动画
57
+ animation: {
58
+ type: String as PropType<LayerAnimationType>,
59
+ default: null,
60
+ validator(value: any) {
61
+ return ['translate', 'fade', null].includes(value)
62
+ }
63
+ },
64
+ //是否根据range对象来定位,此时不需要传入node
65
+ useRange: {
66
+ type: Boolean,
67
+ default: false
68
+ }
69
+ }
70
+
71
+ export type LayerPropsType = ExtractPublicPropTypes<typeof LayerProps>