@maas/vue-equipment 0.22.1 → 0.22.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,5 +1,5 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment/nuxt",
3
3
  "configKey": "vueEquipment",
4
- "version": "0.22.0"
4
+ "version": "0.22.2"
5
5
  }
@@ -4,7 +4,7 @@ const functions$1 = [
4
4
  {
5
5
  name: "MagicCommand",
6
6
  "package": "plugins",
7
- lastUpdated: 1708513784000,
7
+ lastUpdated: 1708531485000,
8
8
  docs: "https://maas.egineering/vue-equipment/plugins/MagicCommand/",
9
9
  description: "command"
10
10
  },
@@ -4,14 +4,12 @@
4
4
  :default="true"
5
5
  class="bg-neutral-800 border border-solid border-neutral-600 w-[40rem] max-h-[30rem] rounded-xl overflow-hidden flex flex-col"
6
6
  >
7
- <magic-command-head class="p-2">
7
+ <magic-command-head class="px-2 pt-2">
8
8
  <div class="w-full border border-neutral-600 p-3 border-b-solid">
9
- <magic-command-input>
10
- <input type="text" placeholder="Search" />
11
- </magic-command-input>
9
+ <input type="text" placeholder="Search" />
12
10
  </div>
13
11
  </magic-command-head>
14
- <magic-command-body class="h-full pb-2">
12
+ <magic-command-body class="h-full py-2">
15
13
  <magic-command-group>
16
14
  <h2 class="p-4 text-xs text-neutral-600">Suggestions</h2>
17
15
  <magic-command-item
@@ -21,9 +19,21 @@
21
19
  >
22
20
  <demo-item :is-active="isActive">View Projects</demo-item>
23
21
  </magic-command-item>
22
+ <magic-command-item v-slot="{ isActive }" :callback="toggleDynamicItem">
23
+ <demo-item :is-active="isActive"
24
+ >{{ dynamic ? 'Remove' : 'Add ' }} Filter</demo-item
25
+ >
26
+ </magic-command-item>
24
27
  </magic-command-group>
25
28
  <magic-command-group>
26
29
  <h2 class="p-4 text-xs text-neutral-600">Filter</h2>
30
+ <magic-command-item
31
+ v-slot="{ isActive }"
32
+ v-if="dynamic"
33
+ :callback="() => itemCallback('dynamic')"
34
+ >
35
+ <demo-item :is-active="isActive">All</demo-item>
36
+ </magic-command-item>
27
37
  <magic-command-item
28
38
  v-for="nth in 20"
29
39
  :key="nth"
@@ -38,16 +48,28 @@
38
48
  </template>
39
49
 
40
50
  <script setup lang="ts">
41
- import { inject } from 'vue'
51
+ import { ref, inject } from 'vue'
42
52
  import { useCommandApi, CommandInstanceId } from '@maas/vue-equipment/plugins'
43
53
  import DemoItem from './DemoItem.vue'
44
54
 
55
+ interface Props {
56
+ hasDynamicItem?: boolean
57
+ }
58
+
59
+ defineProps<Props>()
60
+
45
61
  const commandId = inject(CommandInstanceId, '')
46
62
 
47
63
  const commandApi = useCommandApi(commandId)
48
64
  const { selectView } = commandApi
49
65
 
50
- function itemCallback(nth: number) {
66
+ const dynamic = ref(false)
67
+
68
+ function toggleDynamicItem() {
69
+ dynamic.value = !dynamic.value
70
+ }
71
+
72
+ function itemCallback(nth: number | string) {
51
73
  console.log(nth)
52
74
  }
53
75
 
@@ -1,2 +1,14 @@
1
- declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
1
+ interface Props {
2
+ hasDynamicItem?: boolean;
3
+ }
4
+ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<Props>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<Props>>>, {}, {}>;
2
5
  export default _default;
6
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
7
+ type __VLS_TypePropsToRuntimeProps<T> = {
8
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
9
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
10
+ } : {
11
+ type: import('vue').PropType<T[K]>;
12
+ required: true;
13
+ };
14
+ };
@@ -5,9 +5,7 @@
5
5
  >
6
6
  <magic-command-head class="p-2">
7
7
  <div class="w-full border border-neutral-600 p-3 border-b-solid">
8
- <magic-command-input>
9
- <input type="text" placeholder="Search Projects" />
10
- </magic-command-input>
8
+ <input type="text" placeholder="Search Projects" />
11
9
  </div>
12
10
  </magic-command-head>
13
11
  <magic-command-body class="h-full pb-2">
@@ -10,7 +10,6 @@
10
10
  class="magic-command"
11
11
  :id="toValue(id)"
12
12
  :class="toValue(props.class)"
13
- @click.self="close"
14
13
  aria-command="true"
15
14
  >
16
15
  <transition
@@ -176,5 +175,5 @@ provide(CommandOptionsKey, mappedOptions)
176
175
  </script>
177
176
 
178
177
  <style>
179
- :root{--magic-command-z-index:999;--magic-command-backdrop-color:rgba(0,0,0,.5);--magic-command-backdrop-filter:unset;--magic-command-content-align-items:center;--magic-command-content-justify-content:center;--magic-command-content-overflow-y:auto}@keyframes magic-command-content-enter{0%{opacity:0;transform:translateY(2rem)}to{opacity:1;transform:translateY(0)}}@keyframes magic-command-content-leave{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(1.02)}}.magic-command{align-items:center;background:transparent;border:none;color:inherit;display:flex;height:100%;inset:0;justify-content:center;padding:0;position:fixed;width:100%;z-index:var(--magic-command-z-index)}.magic-command__content{-webkit-overflow-scrolling:touch;align-items:var(--magic-command-content-align-items);display:flex;justify-content:var(--magic-command-content-justify-content);max-height:100%;overflow-y:var(--magic-command-content-overflow-y);scroll-behavior:smooth;width:100%}.magic-command__backdrop{-webkit-backdrop-filter:var(--magic-command-backdrop-filter);backdrop-filter:var(--magic-command-backdrop-filter);background-color:var(--magic-command-backdrop-color);bottom:0;height:100%;left:0;position:fixed;right:0;top:0;width:100%;z-index:-1}.magic-command--content-enter-active{animation:magic-command-content-enter .3s ease}.magic-command--content-leave-active{animation:magic-command-content-leave .3s ease}@media (prefers-reduced-motion){.magic-command--content-enter-active{animation:fade-in .3s ease}.magic-command--content-leave-active{animation:fade-out .3s ease}}.magic-command--backdrop-enter-active{animation:fade-in .3s ease}.magic-command--backdrop-leave-active{animation:fade-out .3s ease}
178
+ :root{--magic-command-z-index:999;--magic-command-backdrop-color:rgba(0,0,0,.5);--magic-command-backdrop-filter:unset;--magic-command-content-align-items:center;--magic-command-content-justify-content:center;--magic-command-content-overflow-y:auto}@keyframes magic-command-content-enter{0%{opacity:0;transform:translateY(2rem)}to{opacity:1;transform:translateY(0)}}@keyframes magic-command-content-leave{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(1.02)}}.magic-command{align-items:center;background:transparent;border:none;color:inherit;display:flex;height:100%;inset:0;justify-content:center;padding:0;pointer-events:none;position:fixed;width:100%;z-index:var(--magic-command-z-index)}.magic-command__content{-webkit-overflow-scrolling:touch;align-items:var(--magic-command-content-align-items);display:flex;justify-content:var(--magic-command-content-justify-content);max-height:100%;overflow-y:var(--magic-command-content-overflow-y);pointer-events:auto;scroll-behavior:smooth;width:100%}.magic-command__backdrop{-webkit-backdrop-filter:var(--magic-command-backdrop-filter);backdrop-filter:var(--magic-command-backdrop-filter);background-color:var(--magic-command-backdrop-color);bottom:0;height:100%;left:0;pointer-events:auto;position:fixed;right:0;top:0;width:100%;z-index:-1}.magic-command--content-enter-active{animation:magic-command-content-enter .3s ease}.magic-command--content-leave-active{animation:magic-command-content-leave .3s ease}@media (prefers-reduced-motion){.magic-command--content-enter-active{animation:fade-in .3s ease}.magic-command--content-leave-active{animation:fade-out .3s ease}}.magic-command--backdrop-enter-active{animation:fade-in .3s ease}.magic-command--backdrop-leave-active{animation:fade-out .3s ease}
180
179
  </style>
@@ -19,8 +19,13 @@ const commandId = inject(CommandInstanceId, '')
19
19
  const options = inject(CommandOptionsKey, {} as CommandOptions)
20
20
 
21
21
  const { activeItem, nextItem, prevItem } = useCommandItem(commandId)
22
- const { findElement, isElementAbove, isElementBelow, scrollInFromBottom } =
23
- useCommandScroll(elRef)
22
+ const {
23
+ findElement,
24
+ isElementAbove,
25
+ isElementBelow,
26
+ scrollInFromBottom,
27
+ scrollInFromTop,
28
+ } = useCommandScroll(elRef)
24
29
 
25
30
  const keys = useMagicKeys()
26
31
 
@@ -72,7 +77,7 @@ watch(activeItem, async (value) => {
72
77
  const element = findElement(value)
73
78
  if (element) {
74
79
  if (isElementAbove(element)) {
75
- element.scrollIntoView()
80
+ scrollInFromTop(element)
76
81
  } else if (isElementBelow(element)) {
77
82
  scrollInFromBottom(element)
78
83
  }
@@ -2,7 +2,7 @@
2
2
  <div
3
3
  class="magic-command-item"
4
4
  ref="elRef"
5
- :data-id="mappedId"
5
+ :data-item-id="mappedId"
6
6
  :aria-selected="isActive"
7
7
  >
8
8
  <slot :is-active="isActive" />
@@ -18,6 +18,7 @@ import {
18
18
  nextTick,
19
19
  onMounted,
20
20
  onUnmounted,
21
+ getCurrentInstance,
21
22
  } from 'vue'
22
23
  import { useEventListener, onKeyStroke } from '@vueuse/core'
23
24
  import { uuid } from '@maas/vue-equipment/utils'
@@ -1,11 +1,20 @@
1
1
  <template>
2
- <div class="magic-command-view" v-if="isActive">
2
+ <div class="magic-command-view" v-if="isActive" ref="elRef">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
6
6
 
7
7
  <script lang="ts" setup>
8
- import { computed, inject, toValue, onMounted, onUnmounted } from 'vue'
8
+ import {
9
+ ref,
10
+ computed,
11
+ inject,
12
+ toValue,
13
+ onMounted,
14
+ onUnmounted,
15
+ watch,
16
+ nextTick,
17
+ } from 'vue'
9
18
  import { uuid } from '@maas/vue-equipment/utils'
10
19
  import { useCommandStore } from '../composables/private/useCommandStore'
11
20
  import { useCommandView } from '../composables/private/useCommandView'
@@ -18,6 +27,7 @@ interface Props {
18
27
 
19
28
  const props = withDefaults(defineProps<Props>(), { default: false })
20
29
  const commandId = inject(CommandInstanceId, '')
30
+ const elRef = ref<HTMLElement | undefined>(undefined)
21
31
 
22
32
  const { activeView, selectView } = useCommandView()
23
33
 
@@ -29,7 +39,11 @@ const isActive = computed(() => {
29
39
  return toValue(mappedId) === activeView.value
30
40
  })
31
41
 
32
- const { addView, removeView } = useCommandStore()
42
+ const items = computed(() => {
43
+ return findInstance(toValue(commandId))?.items
44
+ })
45
+
46
+ const { addView, removeView, findInstance, sortItems } = useCommandStore()
33
47
 
34
48
  onMounted(() => {
35
49
  if (toValue(commandId)) {
@@ -46,4 +60,16 @@ onUnmounted(() => {
46
60
  removeView(toValue(commandId), mappedId.value)
47
61
  }
48
62
  })
63
+
64
+ // Update sorting for MagicCommandItems
65
+ watch(
66
+ () => items.value.length,
67
+ () => {
68
+ nextTick(() => {
69
+ if (elRef.value) {
70
+ sortItems(toValue(commandId), elRef.value)
71
+ }
72
+ })
73
+ }
74
+ )
49
75
  </script>
@@ -10,23 +10,27 @@ export function useCommandItem(id) {
10
10
  const { findInstance } = useCommandStore();
11
11
  function nextItem(loop = false) {
12
12
  if (items.value) {
13
- const index = items.value.indexOf(activeItem.value || "");
13
+ const index = items.value.findIndex(
14
+ (item) => item.id === activeItem.value
15
+ );
14
16
  const hasNext = items.value[index + 1] !== void 0;
15
17
  if (hasNext) {
16
- selectItem(items.value[index + 1]);
18
+ selectItem(items.value[index + 1].id);
17
19
  } else if (loop) {
18
- selectItem(items.value[0]);
20
+ selectItem(items.value[0].id);
19
21
  }
20
22
  }
21
23
  }
22
24
  function prevItem(loop = false) {
23
25
  if (items.value) {
24
- const index = items.value.indexOf(activeItem.value || "");
26
+ const index = items.value.findIndex(
27
+ (item) => item.id === activeItem.value
28
+ );
25
29
  const hasPrev = items.value[index - 1] !== void 0;
26
30
  if (hasPrev) {
27
- selectItem(items.value[index - 1]);
31
+ selectItem(items.value[index - 1].id);
28
32
  } else if (loop) {
29
- selectItem(items.value[items.value.length - 1]);
33
+ selectItem(items.value[items.value.length - 1].id);
30
34
  }
31
35
  }
32
36
  }
@@ -3,5 +3,6 @@ export declare function useCommandScroll(parent: MaybeRef<HTMLElement | undefine
3
3
  isElementAbove: (element: MaybeRef<HTMLElement>) => boolean;
4
4
  isElementBelow: (element: MaybeRef<HTMLElement>) => boolean;
5
5
  findElement: (id: string) => HTMLElement | null;
6
+ scrollInFromTop: (element: HTMLElement) => void;
6
7
  scrollInFromBottom: (element: HTMLElement) => void;
7
8
  };
@@ -25,7 +25,15 @@ export function useCommandScroll(parent) {
25
25
  return elementRect.bottom >= parentBottom;
26
26
  }
27
27
  function findElement(id) {
28
- return mappedParent.value.querySelector(`[data-id="${id}"]`);
28
+ return mappedParent.value.querySelector(`[data-item-id="${id}"]`);
29
+ }
30
+ function scrollInFromTop(element) {
31
+ const elementRect = element.getBoundingClientRect();
32
+ const parentRect = mappedParent.value.getBoundingClientRect();
33
+ const scrollAmount = elementRect.top - parentRect.top - paddingTop.value;
34
+ mappedParent.value.scrollBy({
35
+ top: scrollAmount
36
+ });
29
37
  }
30
38
  function scrollInFromBottom(element) {
31
39
  const elementRect = element.getBoundingClientRect();
@@ -39,6 +47,7 @@ export function useCommandScroll(parent) {
39
47
  isElementAbove,
40
48
  isElementBelow,
41
49
  findElement,
50
+ scrollInFromTop,
42
51
  scrollInFromBottom
43
52
  };
44
53
  }
@@ -1,12 +1,19 @@
1
+ type Item = {
2
+ index: number;
3
+ id: string;
4
+ };
1
5
  type CommandInstance = {
2
6
  id: string;
3
- items: string[];
7
+ items: Item[];
4
8
  views: string[];
5
9
  };
6
10
  export declare function useCommandStore(): {
7
11
  commandStore: import("vue").Ref<{
8
12
  id: string;
9
- items: string[];
13
+ items: {
14
+ index: number;
15
+ id: string;
16
+ }[];
10
17
  views: string[];
11
18
  }[]>;
12
19
  addInstance: (id: string) => void;
@@ -14,6 +21,7 @@ export declare function useCommandStore(): {
14
21
  removeInstance: (id: string) => void;
15
22
  addItem: (id: string, item: string) => void;
16
23
  removeItem: (id: string, item: string) => void;
24
+ sortItems: (id: string, parent: HTMLElement) => void;
17
25
  addView: (id: string, view: string) => void;
18
26
  removeView: (id: string, view: string) => void;
19
27
  };
@@ -15,14 +15,26 @@ export function useCommandStore() {
15
15
  (x) => x.id !== id
16
16
  );
17
17
  }
18
+ function sortItems(id, parent) {
19
+ const instance = findInstance(id);
20
+ const itemElements = parent.querySelectorAll("[data-item-id]");
21
+ itemElements.forEach((el, index) => {
22
+ const itemId = el.dataset.itemId;
23
+ const item = instance.items.find((item2) => item2.id === itemId);
24
+ if (item) {
25
+ item.index = index;
26
+ }
27
+ });
28
+ instance.items.sort((a, b) => a.index - b.index);
29
+ }
18
30
  function addItem(id, item) {
19
31
  const instance = findInstance(id);
20
- instance.items.push(item);
32
+ instance.items.push({ index: -1, id: item });
21
33
  }
22
34
  function removeItem(id, item) {
23
35
  const instance = findInstance(id);
24
36
  if (instance) {
25
- instance.items = instance.items.filter((x) => x !== item);
37
+ instance.items = instance.items.filter((x) => x.id !== item);
26
38
  }
27
39
  }
28
40
  function addView(id, view) {
@@ -42,6 +54,7 @@ export function useCommandStore() {
42
54
  removeInstance,
43
55
  addItem,
44
56
  removeItem,
57
+ sortItems,
45
58
  addView,
46
59
  removeView
47
60
  };
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.22.1",
4
+ "version": "0.22.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",