@merkaly/nuxt 0.3.2 → 0.4.0

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.
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.3.2",
7
+ "version": "0.4.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -1,19 +1,25 @@
1
1
  import type { BaseButtonVariant, BaseSize } from 'bootstrap-vue-next';
2
- declare var __VLS_8: {};
2
+ import type { PropType } from 'vue';
3
+ declare var __VLS_14: {};
3
4
  type __VLS_Slots = {} & {
4
- default?: (props: typeof __VLS_8) => any;
5
+ default?: (props: typeof __VLS_14) => any;
5
6
  };
6
7
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
7
8
  size: {
8
9
  type: PropType<keyof BaseSize>;
9
10
  default: () => string;
10
11
  };
12
+ icon: {
13
+ type: StringConstructor;
14
+ default: () => string;
15
+ };
11
16
  text: {
12
17
  type: StringConstructor;
13
18
  default: () => string;
14
19
  };
15
20
  variant: {
16
21
  type: PropType<keyof BaseButtonVariant>;
22
+ default: () => undefined;
17
23
  };
18
24
  solid: {
19
25
  type: BooleanConstructor;
@@ -24,12 +30,17 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
24
30
  type: PropType<keyof BaseSize>;
25
31
  default: () => string;
26
32
  };
33
+ icon: {
34
+ type: StringConstructor;
35
+ default: () => string;
36
+ };
27
37
  text: {
28
38
  type: StringConstructor;
29
39
  default: () => string;
30
40
  };
31
41
  variant: {
32
42
  type: PropType<keyof BaseButtonVariant>;
43
+ default: () => undefined;
33
44
  };
34
45
  solid: {
35
46
  type: BooleanConstructor;
@@ -37,8 +48,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
37
48
  };
38
49
  }>> & Readonly<{}>, {
39
50
  text: string;
40
- size: any;
41
- variant: any;
51
+ size: keyof BaseSize;
52
+ variant: keyof BaseButtonVariant;
53
+ icon: string;
42
54
  solid: boolean;
43
55
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
44
56
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,9 +1,11 @@
1
1
  <script setup>
2
2
  import { computed, useSlots } from "vue";
3
+ import FormatIcon from "../format/FormatIcon.vue";
3
4
  const props = defineProps({
4
5
  size: { type: String, default: () => "sm" },
5
- text: { type: String, default: () => "Actions" },
6
- variant: { type: String },
6
+ icon: { type: String, default: () => "ellipsis-v" },
7
+ text: { type: String, default: () => "" },
8
+ variant: { type: String, default: () => void 0 },
7
9
  solid: { type: Boolean, default: () => false }
8
10
  });
9
11
  const slots = useSlots();
@@ -11,7 +13,16 @@ const noDefault = computed(() => !slots.default);
11
13
  </script>
12
14
 
13
15
  <template>
14
- <BDropdown :disabled="noDefault" :size="props.size" :text="props.text" :variant="props.variant" auto-close="outside">
16
+ <BDropdown
17
+ :disabled="noDefault"
18
+ :size="props.size"
19
+ :text="props.text"
20
+ :variant="props.variant"
21
+ auto-close="outside"
22
+ no-caret>
23
+ <template #button-content>
24
+ <FormatIcon :name="props.icon" :text="props.text" />
25
+ </template>
15
26
  <slot />
16
27
  </BDropdown>
17
28
  </template>
@@ -1,19 +1,25 @@
1
1
  import type { BaseButtonVariant, BaseSize } from 'bootstrap-vue-next';
2
- declare var __VLS_8: {};
2
+ import type { PropType } from 'vue';
3
+ declare var __VLS_14: {};
3
4
  type __VLS_Slots = {} & {
4
- default?: (props: typeof __VLS_8) => any;
5
+ default?: (props: typeof __VLS_14) => any;
5
6
  };
6
7
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
7
8
  size: {
8
9
  type: PropType<keyof BaseSize>;
9
10
  default: () => string;
10
11
  };
12
+ icon: {
13
+ type: StringConstructor;
14
+ default: () => string;
15
+ };
11
16
  text: {
12
17
  type: StringConstructor;
13
18
  default: () => string;
14
19
  };
15
20
  variant: {
16
21
  type: PropType<keyof BaseButtonVariant>;
22
+ default: () => undefined;
17
23
  };
18
24
  solid: {
19
25
  type: BooleanConstructor;
@@ -24,12 +30,17 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
24
30
  type: PropType<keyof BaseSize>;
25
31
  default: () => string;
26
32
  };
33
+ icon: {
34
+ type: StringConstructor;
35
+ default: () => string;
36
+ };
27
37
  text: {
28
38
  type: StringConstructor;
29
39
  default: () => string;
30
40
  };
31
41
  variant: {
32
42
  type: PropType<keyof BaseButtonVariant>;
43
+ default: () => undefined;
33
44
  };
34
45
  solid: {
35
46
  type: BooleanConstructor;
@@ -37,8 +48,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
37
48
  };
38
49
  }>> & Readonly<{}>, {
39
50
  text: string;
40
- size: any;
41
- variant: any;
51
+ size: keyof BaseSize;
52
+ variant: keyof BaseButtonVariant;
53
+ icon: string;
42
54
  solid: boolean;
43
55
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
44
56
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -81,8 +81,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
81
81
  }>, {
82
82
  mode: PlaceTypes;
83
83
  disabled: boolean;
84
- countries: string[];
85
84
  placeholder: string;
85
+ countries: string[];
86
86
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
87
87
  declare const _default: typeof __VLS_export;
88
88
  export default _default;
@@ -81,8 +81,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
81
81
  }>, {
82
82
  mode: PlaceTypes;
83
83
  disabled: boolean;
84
- countries: string[];
85
84
  placeholder: string;
85
+ countries: string[];
86
86
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
87
87
  declare const _default: typeof __VLS_export;
88
88
  export default _default;
@@ -7,6 +7,10 @@ declare const __VLS_export: <G>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
7
7
  type: StringConstructor;
8
8
  default: () => string;
9
9
  };
10
+ hideHeader: {
11
+ type: BooleanConstructor;
12
+ default: boolean;
13
+ };
10
14
  hideFooter: {
11
15
  type: BooleanConstructor;
12
16
  default: boolean;
@@ -40,6 +44,11 @@ declare const __VLS_export: <G>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
40
44
  item: G;
41
45
  key: string;
42
46
  }) => any) | undefined;
47
+ } & {
48
+ bulk?: (props: {
49
+ items: G[];
50
+ count: number;
51
+ }) => any;
43
52
  } & {
44
53
  search?: (props: {}) => any;
45
54
  } & {
@@ -9,6 +9,7 @@ const emit = defineEmits(["fetch", "toggle:item"]);
9
9
  const slots = useSlots();
10
10
  const props = defineProps({
11
11
  emptyText: { type: String, default: () => "No items found" },
12
+ hideHeader: { type: Boolean, default: false },
12
13
  hideFooter: { type: Boolean, default: false },
13
14
  hidePagination: { type: Boolean, default: false },
14
15
  hideSelect: { type: Boolean, default: false }
@@ -17,8 +18,9 @@ const $datagrid = defineModel({ type: Object, ...{ type: Object, required: true
17
18
  const instance = getCurrentInstance();
18
19
  const canFetch = Boolean(instance?.vnode?.props?.onFetch);
19
20
  const canFilter = Boolean(slots.filters);
20
- const hasDetails = computed(() => Boolean(slots["details"]));
21
- const hasActions = computed(() => Boolean(slots["actions"]));
21
+ const hasDetailsSlot = computed(() => Boolean(slots["details"]));
22
+ const hasActionsSlot = computed(() => Boolean(slots["actions"]));
23
+ const hasBulkSlot = computed(() => Boolean(slots["bulk"]));
22
24
  const visibleColumns = computed(() => Object.entries($datagrid.value.columns));
23
25
  const tableColspan = computed(() => {
24
26
  const baseColumns = 2;
@@ -50,9 +52,10 @@ const visibleItems = computed(() => {
50
52
  const start = Math.max(0, paginationText.value.values.current - 1);
51
53
  return $datagrid.value.items.slice(start, paginationText.value.values.final);
52
54
  });
55
+ const selectedItems = computed(() => $datagrid.value.items.filter((it) => it._checked));
53
56
  const checkboxAllAttrs = computed(() => {
54
57
  const attrs = {};
55
- const values = $datagrid.value.items.map((it) => it._checked);
58
+ const values = selectedItems.value.map((it) => it._checked);
56
59
  const allChecked = values.length > 0 && values.every(Boolean);
57
60
  const someChecked = values.some(Boolean);
58
61
  attrs["checked"] = allChecked;
@@ -71,18 +74,28 @@ function toggleDetails(item) {
71
74
  record._showDetails = !record._showDetails;
72
75
  emit("toggle:item", item, Boolean(record._showDetails));
73
76
  }
77
+ function emitSearch() {
78
+ $datagrid.value.page = 1;
79
+ emit("fetch", "search");
80
+ }
74
81
  </script>
75
82
 
76
83
  <template>
77
84
  <BCard no-body>
78
- <BCardHeader class="align-items-center p-4">
85
+ <BCardHeader v-if="!props.hideHeader" class="align-items-center p-4">
79
86
  <BCardTitle>
87
+ <div v-if="hasBulkSlot && !props.hideSelect && selectedItems.length" class="w-35px">
88
+ <DropdownIcon icon="caret-down" size="sm" toggle-class="p-2">
89
+ <slot name="bulk" v-bind="{ items: selectedItems, count: selectedItems.length }" />
90
+ </DropdownIcon>
91
+ </div>
92
+
80
93
  <slot name="search">
81
94
  <InputSearch
82
95
  v-model="$datagrid.search"
83
96
  :disabled="$datagrid.loading"
84
- class="w-250px"
85
- @change="emit('fetch', 'search')" />
97
+ class="max-w-250px"
98
+ @change="emitSearch()" />
86
99
  </slot>
87
100
  </BCardTitle>
88
101
 
@@ -144,7 +157,7 @@ function toggleDetails(item) {
144
157
  table-class="align-middle table-row-dashed gy-3 h-100">
145
158
  <BThead class="sticky-top z-index-1">
146
159
  <BTr class="text-start text-body-secondary fw-bold fs-7 text-uppercase gs-0">
147
- <BTh v-if="hasDetails" class="p-0 w-25px" />
160
+ <BTh v-if="hasDetailsSlot" class="p-0 w-25px" />
148
161
 
149
162
  <BTh v-if="!props.hideSelect" class="w-40px px-0">
150
163
  <div class="form-check form-check-sm form-check-custom cell-checkbox">
@@ -165,7 +178,7 @@ function toggleDetails(item) {
165
178
  </BTh>
166
179
  </template>
167
180
 
168
- <BTh v-if="hasActions" class="text-end px-3" />
181
+ <BTh v-if="hasActionsSlot" class="text-end px-3" />
169
182
  </BTr>
170
183
  </BThead>
171
184
 
@@ -188,7 +201,7 @@ function toggleDetails(item) {
188
201
  <BTbody v-else class="fw-semibold text-gray-600">
189
202
  <template v-for="(item, idx) in visibleItems" :key="idx">
190
203
  <BTr>
191
- <BTd v-if="hasDetails" class="p-0 w-25px">
204
+ <BTd v-if="hasDetailsSlot" class="p-0 w-25px">
192
205
  <BButton
193
206
  class="w-25px h-100 rounded-0 p-0 bg-light bg-hover-light-secondary border-end border-dashed"
194
207
  size="sm"
@@ -212,14 +225,14 @@ function toggleDetails(item) {
212
225
  </BTd>
213
226
  </template>
214
227
 
215
- <BTd v-if="hasActions" class="text-end px-3">
216
- <DropdownIcon toggle-class="border border-secondary-subtle border-dashed text-body">
228
+ <BTd v-if="hasActionsSlot" class="text-end px-3">
229
+ <DropdownIcon toggle-class="border border-secondary-subtle border-dashed text-body py-1 px-3">
217
230
  <slot :index="idx" :item="item" name="actions" />
218
231
  </DropdownIcon>
219
232
  </BTd>
220
233
  </BTr>
221
234
 
222
- <BTr v-if="hasDetails && item._showDetails">
235
+ <BTr v-if="hasDetailsSlot && item._showDetails">
223
236
  <BTd :colspan="tableColspan" class="p-0">
224
237
  <slot
225
238
  :index="idx"
@@ -7,6 +7,10 @@ declare const __VLS_export: <G>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
7
7
  type: StringConstructor;
8
8
  default: () => string;
9
9
  };
10
+ hideHeader: {
11
+ type: BooleanConstructor;
12
+ default: boolean;
13
+ };
10
14
  hideFooter: {
11
15
  type: BooleanConstructor;
12
16
  default: boolean;
@@ -40,6 +44,11 @@ declare const __VLS_export: <G>(__VLS_props: NonNullable<Awaited<typeof __VLS_se
40
44
  item: G;
41
45
  key: string;
42
46
  }) => any) | undefined;
47
+ } & {
48
+ bulk?: (props: {
49
+ items: G[];
50
+ count: number;
51
+ }) => any;
43
52
  } & {
44
53
  search?: (props: {}) => any;
45
54
  } & {
@@ -1,20 +1,13 @@
1
1
  interface NavigationItem {
2
- text: string | null;
3
- path: string;
2
+ disabled?: boolean;
4
3
  loading?: boolean;
4
+ path: string;
5
+ text: string | null;
5
6
  }
6
7
  type NavigationItemOrGetter = NavigationItem | (() => NavigationItem);
7
8
  export declare function useNavigation(page?: NavigationItemOrGetter): {
8
- current: import("vue").ComputedRef<{
9
- path: string;
10
- text: string | null;
11
- loading: boolean;
12
- } | undefined>;
13
- items: import("vue").ComputedRef<{
14
- path: string;
15
- text: string | null;
16
- loading: boolean;
17
- }[]>;
9
+ current: import("vue").ComputedRef<NavigationItem | undefined>;
10
+ items: import("vue").ComputedRef<NavigationItem[]>;
18
11
  defer: (route: {
19
12
  path: string;
20
13
  }) => void;
@@ -3,49 +3,54 @@ import { useState } from "#imports";
3
3
  export function useNavigation(page) {
4
4
  const list = useState("breadcrumbs", () => []);
5
5
  const pendingRoute = useState("breadcrumbs:pending", () => null);
6
- function normalizePath(base, path) {
7
- return `${base.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
8
- }
9
- function resolve(item) {
10
- return typeof item === "function" ? item() : item;
11
- }
6
+ const resolveItem = (item) => typeof item === "function" ? item() : item;
7
+ const normalizePath = (base, path) => `${base.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
8
+ const isVisibleItem = (item) => item.text != null && !item.loading;
12
9
  const resolved = computed(() => {
13
10
  let uri = "";
14
- return list.value.map((item) => {
15
- const { text, path = "", loading } = resolve(item);
16
- uri = normalizePath(uri, path);
17
- return { path: uri, text, loading: !!loading };
11
+ return list.value.map((rawItem) => {
12
+ const item = resolveItem(rawItem);
13
+ uri = normalizePath(uri, item.path ?? "");
14
+ return {
15
+ disabled: item.disabled,
16
+ loading: !!item.loading,
17
+ path: uri,
18
+ text: item.text
19
+ };
18
20
  });
19
21
  });
20
- const items = computed(() => {
21
- return resolved.value.filter(({ text, loading }) => text != null && !loading);
22
- });
23
- const current = computed(() => {
24
- return resolved.value.at(-1);
25
- });
22
+ const items = computed(() => resolved.value.filter(isVisibleItem));
23
+ const current = computed(() => resolved.value.at(-1));
26
24
  function regenerate() {
27
25
  if (!pendingRoute.value) return;
28
26
  const route = pendingRoute.value;
29
27
  pendingRoute.value = null;
30
- const itemIndex = resolved.value.findLastIndex((value) => route.startsWith(value.path));
31
- if (itemIndex >= 0) {
32
- list.value = list.value.slice(0, itemIndex + 1);
33
- return;
34
- }
35
- list.value = [];
36
- }
37
- if (page) {
38
- regenerate();
39
- const { path } = resolve(page);
40
- const existingIndex = list.value.findIndex((i) => resolve(i).path === path);
41
- if (existingIndex >= 0) {
42
- list.value[existingIndex] = page;
43
- } else {
44
- list.value.push(page);
45
- }
28
+ const index = findLastMatchingIndex(route);
29
+ list.value = index >= 0 ? list.value.slice(0, index + 1) : [];
46
30
  }
47
31
  function defer(route) {
48
32
  pendingRoute.value = route.path;
49
33
  }
34
+ function findLastMatchingIndex(route) {
35
+ return resolved.value.findLastIndex(
36
+ (item) => route.startsWith(item.path)
37
+ );
38
+ }
39
+ function upsertPage(page2) {
40
+ const { path } = resolveItem(page2);
41
+ const index = list.value.findIndex(
42
+ (item) => resolveItem(item).path === path
43
+ );
44
+ if (index >= 0) {
45
+ list.value[index] = page2;
46
+ return;
47
+ }
48
+ list.value.push(page2);
49
+ }
50
+ if (!page) {
51
+ return { current, items, defer, regenerate };
52
+ }
53
+ regenerate();
54
+ upsertPage(page);
50
55
  return { current, items, defer, regenerate };
51
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merkaly/nuxt",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/merkaly-io/nuxt.git"
@@ -42,9 +42,9 @@
42
42
  "test:watch": "vitest watch"
43
43
  },
44
44
  "dependencies": {
45
- "@auth0/auth0-spa-js": "^2.14.0",
45
+ "@auth0/auth0-spa-js": "^2.15.0",
46
46
  "@bootstrap-vue-next/nuxt": "^0.43.0",
47
- "@nuxt/devtools": "^3.1.0",
47
+ "@nuxt/devtools": "^3.2.1",
48
48
  "@nuxt/eslint": "1.13.0",
49
49
  "@nuxt/eslint-config": "^1.13.0",
50
50
  "@nuxt/fonts": "0.13.0",