@@ -12,7 +12,8 @@ const contextmenuMathRandom = computed(() =>
12
12
Math .floor (Math .random () * 1000000 ),
13
13
)
14
14
15
- async function showContextMenu(attachObj : HTMLElement | MouseEvent , offset : MenuOffsetKind = MenuOffsetKind .MEDIUM_TOP , size : MenuSizeKind = MenuSizeKind .MEDIUM , force : boolean = false ) {
15
+ async function showContextMenu(attachObj : HTMLElement | MouseEvent , offset : MenuOffsetKind = MenuOffsetKind .MEDIUM_TOP , size : MenuSizeKind | MenuCustomSize = MenuSizeKind .MEDIUM , force : boolean = false , boundaryEle ? : HTMLElement ,
16
+ ) {
16
17
const contextmenuEle = contextmenuRef .value !
17
18
if (! is_init .value && EVENTS .init [contextmenuEle .id ]) {
18
19
EVENTS .init [contextmenuEle .id ].callback (contextmenuEle )
@@ -55,6 +56,12 @@ async function showContextMenu(attachObj: HTMLElement | MouseEvent, offset: Menu
55
56
padding = 4
56
57
break
57
58
}
59
+ default : {
60
+ minHeight = size .height ?? 80
61
+ minWidth = size .width ?? 160
62
+ padding = 3
63
+ break
64
+ }
58
65
}
59
66
60
67
const contextMenuEle = contextmenuRef .value as HTMLElement
@@ -115,7 +122,12 @@ async function showContextMenu(attachObj: HTMLElement | MouseEvent, offset: Menu
115
122
}
116
123
}
117
124
contextMenuEle .style .left = ` ${left }px `
125
+ contextMenuEle .dataset .left = ` ${left + window .scrollX } `
118
126
contextMenuEle .style .top = ` ${top }px `
127
+ contextMenuEle .dataset .top = ` ${top + window .scrollY } `
128
+
129
+ addBoundaryAdjustment (contextMenuEle , boundaryEle )
130
+
119
131
contextMenuEle .style .visibility = ' visible'
120
132
121
133
contextMenuEle .querySelectorAll (' .iw-contextmenu__item' ).forEach ((node ) => {
@@ -136,6 +148,35 @@ async function showContextMenu(attachObj: HTMLElement | MouseEvent, offset: Menu
136
148
})
137
149
}
138
150
151
+ function addBoundaryAdjustment(contextMenuEle : HTMLElement , boundaryEle ? : HTMLElement ) {
152
+ if (boundaryEle ) {
153
+ const observer = new ResizeObserver ((_ ) => {
154
+ let left = contextMenuEle .offsetLeft
155
+ let top = contextMenuEle .offsetTop
156
+
157
+ const boundaryEleRect = boundaryEle .getBoundingClientRect ()
158
+ if (left < boundaryEleRect .left ) {
159
+ left = boundaryEleRect .left
160
+ }
161
+ if (top < boundaryEleRect .top ) {
162
+ top = boundaryEleRect .top
163
+ }
164
+ if ((left + contextMenuEle .offsetWidth ) > boundaryEleRect .right ) {
165
+ left = boundaryEleRect .right - contextMenuEle .offsetWidth
166
+ }
167
+
168
+ if ((top + contextMenuEle .offsetHeight ) > boundaryEleRect .bottom ) {
169
+ top = boundaryEleRect .bottom - contextMenuEle .offsetHeight
170
+ }
171
+ contextMenuEle .style .left = ` ${left }px `
172
+ contextMenuEle .dataset .left = ` ${left + window .scrollX } `
173
+ contextMenuEle .style .top = ` ${top }px `
174
+ contextMenuEle .dataset .top = ` ${top + window .scrollY } `
175
+ })
176
+ observer .observe (contextMenuEle )
177
+ }
178
+ }
179
+
139
180
function hideUnActiveContextMenus(event : MouseEvent ) {
140
181
const contextmenuEles = Array .from (document .querySelectorAll (' .iw-contextmenu' ))
141
182
.filter (ele => ele instanceof HTMLElement && (ele as HTMLElement ).style .display !== ' none' )
@@ -178,9 +219,12 @@ onMounted(() => {
178
219
window .addEventListener (' scroll' , () => {
179
220
const contextmenuEles = document .querySelectorAll (' .iw-contextmenu' )
180
221
for (const i in contextmenuEles ) {
181
- if (! (contextmenuEles [i ] instanceof HTMLElement ) || (contextmenuEles [i ] as HTMLElement ).style .display === ' none' )
222
+ if (! (contextmenuEles [i ] instanceof HTMLElement ) || (contextmenuEles [i ] as HTMLElement ).style .display === ' none' ) {
182
223
continue
183
- doCloseContextMenu (contextmenuEles [i ] as HTMLElement )
224
+ }
225
+ const contextMenuEle = contextmenuEles [i ] as HTMLElement
226
+ contextMenuEle .style .top = ` ${Number .parseInt (contextMenuEle .dataset .top ! ) - window .scrollY }px `
227
+ contextMenuEle .style .left = ` ${Number .parseInt (contextMenuEle .dataset .left ! ) - window .scrollX }px `
184
228
}
185
229
})
186
230
})
@@ -230,6 +274,11 @@ export enum MenuSizeKind {
230
274
LARGE ,
231
275
}
232
276
277
+ export interface MenuCustomSize {
278
+ width? : number
279
+ height? : number
280
+ }
281
+
233
282
export const FUN_CLOSE_CONTEXT_MENU_TYPE = Symbol (' FUN_CLOSE_CONTEXT_MENU_TYPE' ) as InjectionKey <() => void >
234
283
235
284
const EVENTS: {
0 commit comments