@maas/vue-equipment 0.30.2 → 0.30.3

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment/nuxt",
3
3
  "configKey": "vueEquipment",
4
- "version": "0.30.1",
4
+ "version": "0.30.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.0",
7
7
  "unbuild": "unknown"
@@ -19,8 +19,8 @@ import {
19
19
  onMounted,
20
20
  onUnmounted,
21
21
  } from 'vue'
22
- import { useEventListener, onKeyStroke } from '@vueuse/core'
23
22
  import { uuid } from '@maas/vue-equipment/utils'
23
+ import { useEventListener, onKeyStroke } from '@vueuse/core'
24
24
  import { useCommandStore } from '../composables/private/useCommandStore'
25
25
  import { useCommandItem } from '../composables/private/useCommandItem'
26
26
  import { MagicCommandInstanceId } from '../symbols'
@@ -43,7 +43,7 @@ const commandId = inject(MagicCommandInstanceId, '')
43
43
  const { selectItem, activeItem } = useCommandItem(commandId)
44
44
 
45
45
  const mappedId = computed(() => {
46
- return props.id || uuid()
46
+ return props.id ?? uuid()
47
47
  })
48
48
 
49
49
  const isActive = computed(() => {
@@ -34,7 +34,7 @@ const elRef = ref<HTMLElement | undefined>(undefined)
34
34
  const { activeView, selectView } = useCommandView()
35
35
 
36
36
  const mappedId = computed(() => {
37
- return props.id || uuid()
37
+ return props.id ?? uuid()
38
38
  })
39
39
 
40
40
  const isActive = computed(() => {
@@ -31,6 +31,20 @@
31
31
  </magic-menu-float>
32
32
  </div>
33
33
  </transition>
34
+ <span
35
+ v-for="point in coords"
36
+ :style="{
37
+ background: 'red',
38
+ position: 'fixed',
39
+ top: point.y + 'px',
40
+ left: point.x + 'px',
41
+ width: '4px',
42
+ height: '4px',
43
+ zIndex: 1000,
44
+ pointerEvents: 'none',
45
+ transform: 'translate(-50%, -50%)',
46
+ }"
47
+ />
34
48
  </teleport>
35
49
  </template>
36
50
 
@@ -124,20 +138,6 @@ const {
124
138
  wrapperActive,
125
139
  })
126
140
 
127
- // Handle cursor
128
- const mappedClick = computed(() => view?.click)
129
- const mappedPlacement = computed(() => view?.placement ?? 'bottom')
130
- const mappedTrigger = computed(
131
- () => document.querySelector(`[data-id="${viewId}-trigger"]`) as HTMLElement
132
- )
133
-
134
- const { destroy, initialize, isInsideTriangle, isInsideTo } = useMenuCursor({
135
- from: mappedTrigger,
136
- to: contentRef,
137
- placement: mappedPlacement,
138
- click: mappedClick,
139
- })
140
-
141
141
  // Handle state
142
142
  async function onOpen() {
143
143
  wrapperActive.value = true
@@ -152,14 +152,6 @@ function onClose() {
152
152
  innerActive.value = false
153
153
  }
154
154
 
155
- function disableCursor() {
156
- state.input.disabled = [...state.input.disabled, 'pointer']
157
- }
158
-
159
- function enableCursor() {
160
- state.input.disabled = state.input.disabled.filter((x) => x !== 'pointer')
161
- }
162
-
163
155
  watch(
164
156
  () => view?.active,
165
157
  async (value) => {
@@ -171,6 +163,24 @@ watch(
171
163
  }
172
164
  )
173
165
 
166
+ // Handle cursor
167
+ const {
168
+ coords,
169
+ destroy,
170
+ initialize,
171
+ isInsideTriangle,
172
+ isInsideTo,
173
+ isInsideFrom,
174
+ } = useMenuCursor(view!)
175
+
176
+ function disableCursor() {
177
+ state.input.disabled = [...state.input.disabled, 'pointer']
178
+ }
179
+
180
+ function enableCursor() {
181
+ state.input.disabled = state.input.disabled.filter((x) => x !== 'pointer')
182
+ }
183
+
174
184
  watch(isInsideTriangle, (value) => {
175
185
  if (value) {
176
186
  disableCursor()
@@ -182,17 +192,23 @@ watch(isInsideTriangle, (value) => {
182
192
  watch(isInsideTo, (value) => {
183
193
  if (value) {
184
194
  enableCursor()
185
- } else {
195
+ }
196
+ })
197
+
198
+ const isOutside = computed(
199
+ () => !isInsideTo.value && !isInsideFrom.value && !isInsideTriangle.value
200
+ )
201
+
202
+ watch(isOutside, (value, oldValue) => {
203
+ if (value && !oldValue) {
186
204
  switch (state.options.mode) {
187
205
  case 'navigation':
188
- if (!isInsideTriangle.value) {
189
- view!.active = false
190
- }
206
+ view!.active = false
191
207
  }
192
208
  }
193
209
  })
194
210
 
195
- onBeforeUnmount(async () => {
211
+ onBeforeUnmount(() => {
196
212
  destroy()
197
213
  })
198
214
 
@@ -53,7 +53,6 @@ if (!viewId) {
53
53
  if (!contentId) {
54
54
  throw new Error('MagicMenuItem must be nested inside MagicMenuContent')
55
55
  }
56
-
57
56
  const mappedId = computed(() => props.id ?? `magic-menu-item-${uuid()}`)
58
57
 
59
58
  // Register item
@@ -8,7 +8,6 @@
8
8
  import { computed, inject, onBeforeUnmount, provide } from 'vue'
9
9
  import { uuid } from '@maas/vue-equipment/utils'
10
10
  import { useMenuView } from '../composables/private/useMenuView'
11
-
12
11
  import {
13
12
  MagicMenuInstanceId,
14
13
  MagicMenuViewId,
@@ -1,13 +1,5 @@
1
- import { type MaybeRef } from 'vue';
2
- import type { Coordinates } from '../../types.js';
3
- import type { Placement } from '@floating-ui/vue';
4
- interface UseMenuCursorArgs {
5
- from: MaybeRef<HTMLElement | undefined>;
6
- to: MaybeRef<HTMLElement | undefined>;
7
- placement: MaybeRef<Placement>;
8
- click: MaybeRef<Coordinates | undefined>;
9
- }
10
- export declare function useMenuCursor(args: UseMenuCursorArgs): {
1
+ import type { MenuView } from '../../types.js';
2
+ export declare function useMenuCursor(view: MenuView): {
11
3
  coords: import("vue").Ref<{
12
4
  x: number;
13
5
  y: number;
@@ -18,4 +10,3 @@ export declare function useMenuCursor(args: UseMenuCursorArgs): {
18
10
  initialize: () => void;
19
11
  destroy: () => void;
20
12
  };
21
- export {};
@@ -1,14 +1,7 @@
1
- import { ref, toValue } from "vue";
2
- import {
3
- useEventListener,
4
- useElementBounding,
5
- useResizeObserver,
6
- usePointer
7
- } from "@vueuse/core";
8
- export function useMenuCursor(args) {
9
- const cancelListener = ref(new AbortController());
10
- const { x, y } = usePointer();
11
- const { from, to, placement, click } = args;
1
+ import { ref } from "vue";
2
+ import { useEventListener } from "@vueuse/core";
3
+ export function useMenuCursor(view) {
4
+ let cancelListener = new AbortController();
12
5
  const coords = ref([
13
6
  { x: 0, y: 0 },
14
7
  { x: 0, y: 0 },
@@ -19,7 +12,7 @@ export function useMenuCursor(args) {
19
12
  const isInsideTriangle = ref(false);
20
13
  function extendTriangle(vertices, pixelAmount) {
21
14
  const [a, b, c] = vertices;
22
- switch (toValue(placement)) {
15
+ switch (view?.placement) {
23
16
  case "bottom":
24
17
  case "bottom-start":
25
18
  case "bottom-end":
@@ -66,8 +59,8 @@ export function useMenuCursor(args) {
66
59
  coords.value = [a, b, c];
67
60
  return [a, b, c];
68
61
  }
69
- function isPointInTriangle(args2) {
70
- const { p, a, b, c } = args2;
62
+ function isPointInTriangle(args) {
63
+ const { p, a, b, c } = args;
71
64
  const v0 = { x: c.x - a.x, y: c.y - a.y };
72
65
  const v1 = { x: b.x - a.x, y: b.y - a.y };
73
66
  const v2 = { x: p.x - a.x, y: p.y - a.y };
@@ -81,37 +74,29 @@ export function useMenuCursor(args) {
81
74
  const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
82
75
  return u >= 0 && v >= 0 && u + v <= 1;
83
76
  }
84
- function isPointInRectangle(args2) {
85
- const { p, top, left, bottom, right } = args2;
77
+ function isPointInRectangle(args) {
78
+ const { p, top, left, bottom, right } = args;
86
79
  return p.x >= left && p.x <= right && p.y >= top && p.y <= bottom;
87
80
  }
88
- function triangleOverlap(cursor, from2, to2) {
89
- const fromBounding = useElementBounding(from2, {
90
- windowScroll: false,
91
- windowResize: false
92
- });
93
- const toBounding = useElementBounding(to2, {
94
- windowScroll: false,
95
- windowResize: false
96
- });
81
+ function triangleOverlap(cursor, fromBounding, toBounding) {
97
82
  const { top, left, bottom, right } = toBounding;
98
- const centerPoint = toValue(click) ?? {
99
- x: (fromBounding.left.value + fromBounding.right.value) / 2,
100
- y: (fromBounding.top.value + fromBounding.bottom.value) / 2
83
+ const centerPoint = view.click ? view.click : {
84
+ x: (fromBounding.left + fromBounding.right) / 2,
85
+ y: (fromBounding.top + fromBounding.bottom) / 2
101
86
  };
102
87
  const sidePoints = [];
103
- switch (toValue(placement)) {
88
+ switch (view.placement) {
104
89
  case "top":
105
90
  case "top-start":
106
91
  case "top-end":
107
92
  case "bottom":
108
93
  case "bottom-start":
109
94
  case "bottom-end":
110
- const topDist = Math.abs(top.value - centerPoint.y);
111
- const bottomDist = Math.abs(bottom.value - centerPoint.y);
95
+ const topDist = Math.abs(top - centerPoint.y);
96
+ const bottomDist = Math.abs(bottom - centerPoint.y);
112
97
  const mappedY = topDist < bottomDist ? top : bottom;
113
- sidePoints.push({ x: left.value, y: mappedY.value });
114
- sidePoints.push({ x: right.value, y: mappedY.value });
98
+ sidePoints.push({ x: left, y: mappedY });
99
+ sidePoints.push({ x: right, y: mappedY });
115
100
  break;
116
101
  case "right":
117
102
  case "right-start":
@@ -119,11 +104,11 @@ export function useMenuCursor(args) {
119
104
  case "left":
120
105
  case "left-start":
121
106
  case "left-end":
122
- const rightDist = Math.abs(right.value - centerPoint.x);
123
- const leftDist = Math.abs(left.value - centerPoint.x);
107
+ const rightDist = Math.abs(right - centerPoint.x);
108
+ const leftDist = Math.abs(left - centerPoint.x);
124
109
  const mappedX = rightDist < leftDist ? right : left;
125
- sidePoints.push({ x: mappedX.value, y: top.value });
126
- sidePoints.push({ x: mappedX.value, y: bottom.value });
110
+ sidePoints.push({ x: mappedX, y: top });
111
+ sidePoints.push({ x: mappedX, y: bottom });
127
112
  break;
128
113
  }
129
114
  const [a, b, c] = extendTriangle(
@@ -137,69 +122,45 @@ export function useMenuCursor(args) {
137
122
  c
138
123
  });
139
124
  }
140
- function elementOverlap(cursor, element) {
141
- const { top, left, bottom, right } = useElementBounding(element, {
142
- windowScroll: false,
143
- windowResize: false
144
- });
125
+ function elementOverlap(cursor, bounding) {
126
+ const { top, left, bottom, right } = bounding;
145
127
  return isPointInRectangle({
146
128
  p: cursor,
147
- top: top.value,
148
- left: left.value,
149
- bottom: bottom.value,
150
- right: right.value
129
+ top,
130
+ left,
131
+ bottom,
132
+ right
151
133
  });
152
134
  }
153
135
  function onMousemove(e) {
154
- const cursor = { x: e.clientX, y: e.clientY };
155
- isInsideFrom.value = elementOverlap(cursor, from);
156
- isInsideTo.value = elementOverlap(cursor, to);
157
- isInsideTriangle.value = triangleOverlap(cursor, from, to);
158
- }
159
- function fromMouseenter() {
160
- isInsideFrom.value = true;
161
- }
162
- function fromMouseleave() {
163
- isInsideFrom.value = false;
164
- }
165
- function toMouseenter() {
166
- isInsideTo.value = true;
167
- }
168
- function toMouseleave(e) {
169
- isInsideTo.value = false;
170
- }
171
- function onResize() {
172
- const cursor = { x: x.value, y: y.value };
173
- isInsideFrom.value = elementOverlap(cursor, from);
174
- isInsideTo.value = elementOverlap(cursor, to);
175
- isInsideTriangle.value = triangleOverlap(cursor, from, to);
136
+ const from = document.querySelector(
137
+ `[data-id="${view?.id}-trigger"]`
138
+ );
139
+ const to = document.querySelector(
140
+ `[data-id="${view?.id}-content"] .magic-menu-content__inner`
141
+ );
142
+ if (from && to) {
143
+ const cursor = { x: e.clientX, y: e.clientY };
144
+ const fromBounding = from.getBoundingClientRect();
145
+ const toBounding = to.getBoundingClientRect();
146
+ isInsideFrom.value = elementOverlap(cursor, fromBounding);
147
+ isInsideTo.value = elementOverlap(cursor, toBounding);
148
+ isInsideTriangle.value = triangleOverlap(cursor, fromBounding, toBounding);
149
+ }
176
150
  }
177
151
  function initialize() {
178
- cancelListener.value.abort();
179
- cancelListener.value = new AbortController();
180
- useEventListener(from, "mouseenter", fromMouseenter, {
181
- signal: cancelListener.value.signal
182
- });
183
- useEventListener(from, "mouseleave", fromMouseleave, {
184
- signal: cancelListener.value.signal
185
- });
186
- useEventListener(to, "mouseenter", toMouseenter, {
187
- signal: cancelListener.value.signal
188
- });
189
- useEventListener(to, "mouseleave", toMouseleave, {
190
- signal: cancelListener.value.signal
191
- });
152
+ cancelListener.abort();
153
+ cancelListener = new AbortController();
192
154
  useEventListener(document, "mousemove", onMousemove, {
193
- signal: cancelListener.value.signal
155
+ signal: cancelListener.signal
194
156
  });
195
- useResizeObserver(to, onResize);
196
157
  }
197
158
  function destroy() {
198
159
  coords.value = [];
199
160
  isInsideFrom.value = false;
200
161
  isInsideTo.value = false;
201
162
  isInsideTriangle.value = false;
202
- cancelListener.value.abort();
163
+ cancelListener.abort();
203
164
  }
204
165
  return {
205
166
  coords,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment",
3
3
  "description": "A magic collection of Vue composables, plugins, components and directives",
4
- "version": "0.30.2",
4
+ "version": "0.30.3",
5
5
  "author": "Robin Scholz <https://github.com/robinscholz>, Christoph Jeworutzki <https://github.com/ChristophJeworutzki>",
6
6
  "devDependencies": {
7
7
  "@antfu/ni": "^0.21.12",