@quandis/qbo4.ui 4.0.1-CI-20241113-192850 → 4.0.1-CI-20241113-205011

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,13 +7,15 @@ export class QboMenu extends LitElement {
7
7
  @property({ type: String })
8
8
  placement: Placement = "bottom-start";
9
9
 
10
+ @property()
11
+ type: string = "dropdown";
12
+
13
+ @property()
14
+ target: string | null = null;
15
+
10
16
  // Internal state to control menu visibility
11
17
  @state() private isOpen = false;
12
18
 
13
- // Query to find the trigger button and menu container in the shadow DOM
14
- @query("slot") private slotElement!: HTMLSlotElement;
15
- @query('slot[name="menu"]') private menuSlotElement!: HTMLSlotElement;
16
-
17
19
  private triggerButton!: HTMLElement;
18
20
  private menuContainer!: HTMLElement;
19
21
  private middleware = [flip(), shift()];
@@ -22,15 +24,20 @@ export class QboMenu extends LitElement {
22
24
 
23
25
  connectedCallback() {
24
26
  super.connectedCallback();
25
- // document.addEventListener("click", this.handleOutsideClick.bind);
26
- document.addEventListener("qbo-menu-open", this.handleMenuOpen.bind(this));
27
+ document.addEventListener("click", this.handleOutsideClick);
28
+ // document.addEventListener("qbo-menu-open", this.handleMenuOpen);
27
29
  }
28
30
 
29
31
  disconnectedCallback() {
30
32
  super.disconnectedCallback();
31
- // document.removeEventListener("click", this.handleOutsideClick);
32
- document.removeEventListener("qbo-menu-open", this.handleMenuOpen);
33
- this.triggerButton.removeEventListener("click", this.toggleMenu);
33
+ document.removeEventListener("click", this.handleOutsideClick);
34
+ // document.removeEventListener("qbo-menu-open", this.handleMenuOpen);
35
+ if (this.type === "context")
36
+ this.triggerButton.removeEventListener(
37
+ "contextmenu",
38
+ this.showContextMenu
39
+ );
40
+ else this.triggerButton.removeEventListener("click", this.toggleMenu);
34
41
  }
35
42
 
36
43
  handleMenuOpen = (event: Event) => {
@@ -43,9 +50,9 @@ export class QboMenu extends LitElement {
43
50
  };
44
51
 
45
52
  handleOutsideClick = (event: Event) => {
46
- const customEvent = event as PointerEvent;
47
- const target = customEvent.target as HTMLElement;
48
- if (target !== this && !this.contains(target)) {
53
+ const target = event.target as HTMLElement;
54
+ const path = event.composedPath();
55
+ if (!path.includes(this)) {
49
56
  this.closeMenu();
50
57
  }
51
58
  };
@@ -62,38 +69,70 @@ export class QboMenu extends LitElement {
62
69
  this.querySelector("aside") ||
63
70
  (this.querySelector("menu") as HTMLElement);
64
71
 
65
- if (this.triggerButton != null)
66
- this.triggerButton.addEventListener("click", this.toggleMenu);
72
+ if (this.type === "context") {
73
+ if (this.target) {
74
+ this.triggerButton =
75
+ (this.closest(this.target) as HTMLElement) ||
76
+ (() => {
77
+ const rootNode = this.getRootNode();
78
+ if (
79
+ rootNode instanceof ShadowRoot ||
80
+ rootNode instanceof Document
81
+ ) {
82
+ return rootNode.querySelector(this.target);
83
+ }
84
+ return null;
85
+ })() ||
86
+ document.querySelector(this.target) ||
87
+ document;
88
+ }
89
+ this.triggerButton.addEventListener("contextmenu", this.showContextMenu);
90
+ } else {
91
+ if (this.triggerButton != null)
92
+ this.triggerButton.addEventListener("click", this.toggleMenu);
93
+ }
67
94
  }
68
95
 
69
- toggleMenu = (event: Event) => {
70
- if (event.target instanceof HTMLElement
71
- || event.target instanceof SVGElement
72
- || event.target instanceof SVGUseElement) {
73
- let toggleMenu = true;
74
- let parent = event.target.parentElement;
75
- while (toggleMenu && parent) {
76
- if (parent instanceof HTMLElement && parent.tagName.toLowerCase() == 'aside')
77
- toggleMenu = false;
78
- else
79
- parent = parent.parentElement;
80
- }
96
+ showContextMenu = (event: Event) => {
97
+ const clickEvent = event as MouseEvent;
98
+ event.preventDefault();
99
+ event.stopPropagation();
100
+ this.isOpen = true;
101
+ this.menuContainer.classList.toggle("open", this.isOpen);
102
+ const source = {
103
+ getBoundingClientRect: () => ({
104
+ x: clickEvent.clientX,
105
+ y: clickEvent.clientY,
106
+ width: 0,
107
+ height: 0,
108
+ top: clickEvent.clientY,
109
+ left: clickEvent.clientX,
110
+ right: clickEvent.clientX,
111
+ bottom: clickEvent.clientY,
112
+ }),
113
+ };
114
+ this.updateMenuPosition(source);
115
+ };
81
116
 
82
- if (toggleMenu) {
83
- this.isOpen = !this.isOpen;
84
- this.menuContainer.classList.toggle("open", this.isOpen);
85
-
86
- if (this.isOpen) {
87
- this.updateMenuPosition();
88
- document.dispatchEvent(
89
- new CustomEvent("qbo-menu-open", {
90
- bubbles: true,
91
- composed: true,
92
- detail: { menu: this },
93
- })
94
- );
95
- }
96
- }
117
+ toggleMenu = (event: Event) => {
118
+ //event.preventDefault();
119
+ //event.stopPropagation();
120
+ const target = event.target as HTMLElement;
121
+ const path = event.composedPath();
122
+ if (!path.includes(this.triggerButton) || path.includes(this.menuContainer))
123
+ return;
124
+ this.isOpen = !this.isOpen;
125
+ this.menuContainer.classList.toggle("open", this.isOpen);
126
+
127
+ if (this.isOpen) {
128
+ this.updateMenuPosition(this.triggerButton);
129
+ document.dispatchEvent(
130
+ new CustomEvent("qbo-menu-open", {
131
+ bubbles: true,
132
+ composed: true,
133
+ detail: { menu: this },
134
+ })
135
+ );
97
136
  }
98
137
  };
99
138
 
@@ -102,15 +141,13 @@ export class QboMenu extends LitElement {
102
141
  this.menuContainer.classList.remove("open");
103
142
  }
104
143
 
105
- private async updateMenuPosition() {
106
- const { x, y } = await computePosition(
107
- this.triggerButton,
108
- this.menuContainer,
109
- {
110
- placement: this.placement as Placement | undefined,
111
- middleware: this.middleware,
112
- }
113
- );
144
+ private async updateMenuPosition(source: any) {
145
+ console.log(source, typeof source);
146
+ const { x, y } = await computePosition(source, this.menuContainer, {
147
+ placement: this.placement as Placement | undefined,
148
+ middleware: this.middleware,
149
+ strategy: 'fixed'
150
+ });
114
151
 
115
152
  Object.assign(this.menuContainer.style, {
116
153
  left: `${x}px`,