adminforth 2.4.0-next.171 → 2.4.0-next.173

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.
@@ -73,11 +73,12 @@
73
73
  <template #total><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ dataResult.total }}</span></template>
74
74
  </i18n-t>
75
75
  <div class="af-pagination-container flex flex-row items-center xs:flex-row xs:justify-between xs:items-center gap-3">
76
- <div class="inline-flex">
76
+ <div class="inline-flex" :class="isLoading || props.isLoading ? 'pointer-events-none select-none opacity-50' : ''">
77
77
  <!-- Buttons -->
78
78
  <button
79
79
  class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText bg-lightActivePaginationButtonBackground border-r-0 rounded-s hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
80
- @click="currentPage--; pageInput = currentPage.toString();" :disabled="currentPage <= 1">
80
+ @click="currentPage--; pageInput = currentPage.toString();"
81
+ :disabled="currentPage <= 1 || isLoading || props.isLoading">
81
82
  <svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
82
83
  viewBox="0 0 14 10">
83
84
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
@@ -86,12 +87,13 @@
86
87
  </button>
87
88
  <button
88
89
  class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-r-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
89
- @click="switchPage(1); pageInput = currentPage.toString();" :disabled="currentPage <= 1">
90
+ @click="switchPage(1); pageInput = currentPage.toString();"
91
+ :disabled="currentPage <= 1 || isLoading || props.isLoading">
90
92
  <!-- <IconChevronDoubleLeftOutline class="w-4 h-4" /> -->
91
93
  1
92
94
  </button>
93
95
  <div
94
- contenteditable="true"
96
+ :contenteditable="!isLoading && !props.isLoading"
95
97
  class="min-w-10 outline-none inline-block w-auto py-1.5 px-3 text-sm text-center text-lightTablePaginationInputText border border-lightTablePaginationInputBorder bg-lightTablePaginationInputBackground dark:border-darkTablePaginationInputBorder dark:text-darkTablePaginationInputText dark:bg-darkTablePaginationInputBackground z-10"
96
98
  @keydown="onPageKeydown($event)"
97
99
  @input="onPageInput($event)"
@@ -102,14 +104,17 @@
102
104
 
103
105
  <button
104
106
  class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-l-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
105
- @click="currentPage = totalPages; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
107
+ @click="currentPage = totalPages; pageInput = currentPage.toString();"
108
+ :disabled="currentPage >= totalPages || isLoading || props.isLoading"
109
+ >
106
110
  {{ totalPages }}
107
111
 
108
- <!-- <IconChevronDoubleRightOutline class="w-4 h-4" /> -->
109
112
  </button>
110
113
  <button
111
114
  class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText focus:outline-none bg-lightActivePaginationButtonBackground border-l-0 rounded-e hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
112
- @click="currentPage++; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
115
+ @click="currentPage++; pageInput = currentPage.toString();"
116
+ :disabled="currentPage >= totalPages || isLoading || props.isLoading"
117
+ >
113
118
  <svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
114
119
  viewBox="0 0 14 10">
115
120
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
@@ -3,29 +3,24 @@
3
3
  :to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
4
4
  class="af-menu-link flex group relative items-center w-full py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default transition-all duration-200 ease-in-out"
5
5
  :class="{
6
- 'ml-1': isSidebarIconOnly && !isSidebarHovering && isChild,
7
6
  'hover:bg-lightSidebarItemHover hover:text-lightSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextHover active:bg-lightSidebarActive dark:active:bg-darkSidebarHover': !['divider', 'gap', 'heading'].includes(item.type),
8
- 'px-6': (isChild && !isSidebarIconOnly && !isSidebarHovering) || (isChild && isSidebarIconOnly && isSidebarHovering),
9
- 'px-3.5': !isChild || (isSidebarIconOnly && !isSidebarHovering),
10
- 'max-w-12': isSidebarIconOnly && !isSidebarHovering,
7
+ 'pl-6 pr-3.5': (isChild && !isSidebarIconOnly && !isSidebarHovering) || (isChild && isSidebarIconOnly && isSidebarHovering),
8
+ 'px-3.5 ': !isChild || (isSidebarIconOnly && !isSidebarHovering),
9
+ 'w-12': isSidebarIconOnly && !isSidebarHovering,
11
10
  'bg-lightSidebarItemActive dark:bg-darkSidebarItemActive': item.resourceId ?
12
11
  ($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
13
12
  ($route.name === item.path)
14
13
  }"
15
14
  >
16
15
  <component v-if="item.icon" :is="getIcon(item.icon)"
17
- class="text-lightSidebarIcons dark:text-darkSidebarIcons group-hover:text-lightSidebarIconsHover dark:group-hover:text-darkSidebarIconsHover transition-all duration-200 ease-in-out"
18
- :class="{
19
- 'min-w-4 min-h-4': isSidebarIconOnly && !isSidebarHovering && isChild,
20
- 'min-w-5 min-h-5': !(isSidebarIconOnly && !isSidebarHovering && isChild)
21
- }" >
16
+ class="min-w-5 min-h-5 text-lightSidebarIcons dark:text-darkSidebarIcons group-hover:text-lightSidebarIconsHover dark:group-hover:text-darkSidebarIconsHover transition-all duration-200 ease-in-out"
17
+ >
22
18
  </component>
23
- <span
24
- class="overflow-hidden block ms-3 pr-5 text-left rtl:text-right transition-all duration-200 ease-in-out"
19
+ <div
20
+ class="overflow-hidden block ms-3 pr-4 text-left rtl:text-right transition-all duration-200 ease-in-out"
25
21
  :class="{
26
22
  'opacity-0 ms-0 translate-x-4 flex-none': isSidebarIconOnly && !isSidebarHovering,
27
- 'opacity-100 ms-3 translate-x-0 flex-none': isSidebarIconOnly && isSidebarHovering,
28
- 'opacity-100 ms-3 translate-x-0 flex-1': !isSidebarIconOnly
23
+ 'opacity-100 ms-3 translate-x-0 flex-1': !isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering),
29
24
  }"
30
25
  :style="isSidebarIconOnly ? {
31
26
  minWidth: isChild
@@ -37,8 +32,8 @@
37
32
  } : {}"
38
33
  >
39
34
  {{ item.label }}
40
- </span>
41
- <span class="absolute right-1 top-1/2 -translate-y-1/2" v-if="item.badge && (!isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering))">
35
+ </div>
36
+ <span class="absolute right-1 top-1/2 -translate-y-1/2" v-if="item.badge && showExpandedBadge">
42
37
  <Tooltip v-if="item.badgeTooltip">
43
38
  <div class="af-badge inline-flex items-center justify-center h-3 py-2.5 px-1 ms-3 text-xs font-medium rounded-full bg-lightAnnouncementBG dark:bg-darkAnnouncementBG
44
39
  fill-lightAnnouncementText dark:fill-darkAccent text-lightAnnouncementText dark:text-darkAccent min-w-[1.5rem] max-w-[3rem]">{{ item.badge }}</div>
@@ -51,7 +46,7 @@
51
46
  fill-lightAnnouncementText dark:fill-darkAccent text-lightAnnouncementText dark:text-darkAccent min-w-[1.5rem] max-w-[3rem]">{{ item.badge }}</div>
52
47
  </template>
53
48
  </span>
54
- <div v-if="item.badge && isSidebarIconOnly && !isSidebarHovering" class="af-badge absolute right-1 top-1/2 -translate-y-1/2 inline-flex items-center justify-center h-2 w-2 text-sm font-medium rounded-full bg-lightAnnouncementBG dark:bg-darkAnnouncementBG
49
+ <div v-if="item.badge && isSidebarIconOnly && !isSidebarHovering" class="af-badge absolute right-0.5 bottom-1 -translate-y-1/2 inline-flex items-center justify-center h-2 w-2 text-sm font-medium rounded-full bg-lightAnnouncementBG dark:bg-darkAnnouncementBG
55
50
  fill-lightAnnouncementText dark:fill-darkAccent text-lightAnnouncementText dark:text-darkAccent">
56
51
  </div>
57
52
  </RouterLink>
@@ -60,7 +55,55 @@
60
55
  <script setup lang="ts">
61
56
  import { getIcon } from '@/utils';
62
57
  import { Tooltip } from '@/afcl';
58
+ import { ref, watch } from 'vue';
59
+
60
+ const props = defineProps(['item', 'isChild', 'isSidebarIconOnly', 'isSidebarHovering']);
61
+
62
+ const BADGE_SHOW_DELAY_MS = 200;
63
+ const showExpandedBadge = ref(false);
64
+ let showBadgeTimer: ReturnType<typeof setTimeout> | null = null;
65
+
66
+ function cancelShowBadgeTimer() {
67
+ if (showBadgeTimer) {
68
+ clearTimeout(showBadgeTimer);
69
+ showBadgeTimer = null;
70
+ }
71
+ }
72
+
73
+ function showBadgeImmediately() {
74
+ cancelShowBadgeTimer();
75
+ showExpandedBadge.value = true;
76
+ }
77
+
78
+ function hideBadgeImmediately() {
79
+ cancelShowBadgeTimer();
80
+ showExpandedBadge.value = false;
81
+ }
82
+
83
+ function showBadgeAfterDelay() {
84
+ cancelShowBadgeTimer();
85
+ showBadgeTimer = setTimeout(() => {
86
+ showExpandedBadge.value = true;
87
+ showBadgeTimer = null;
88
+ }, BADGE_SHOW_DELAY_MS);
89
+ }
90
+
91
+ watch(
92
+ [() => props.isSidebarIconOnly, () => props.isSidebarHovering],
93
+ ([isIconOnly, isHovering]) => {
94
+ if (!isIconOnly) {
95
+ showBadgeImmediately();
96
+ return;
97
+ }
98
+
99
+ if (isHovering) {
100
+ showBadgeAfterDelay();
101
+ return;
102
+ }
63
103
 
64
- defineProps(['item', 'isChild', 'isSidebarIconOnly', 'isSidebarHovering']);
104
+ hideBadgeImmediately();
105
+ },
106
+ { immediate: true }
107
+ );
65
108
 
66
109
  </script>
@@ -130,7 +130,7 @@
130
130
  </svg>
131
131
  </button>
132
132
 
133
- <ul :id="`dropdown-example${i}`" role="none" class="af-sidebar-dropdown pt-1 space-y-1" :class="{ 'hidden': !opened.includes(i) }">
133
+ <ul :id="`dropdown-example${i}`" role="none" class="af-sidebar-dropdown pt-1 space-y-1" :class="{ 'hidden': !opened.includes(i), 'relative after:absolute after:-left-3 after:inset-y-0 after:w-0.5 after:bg-lightSidebarIcons/50 dark:after:bg-darkSidebarIcons/50 after:rounded-full': isSidebarIconOnly && !isSidebarHovering && opened.includes(i) }">
134
134
  <template v-for="(child, j) in item.children" :key="`menu-${i}-${j}`">
135
135
  <li class="af-sidebar-menu-link">
136
136
  <MenuLink :item="child" isChild="true" @click="$emit('hideSidebar')" :isSidebarIconOnly="isSidebarIconOnly" :isSidebarHovering="isSidebarHovering"/>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "2.4.0-next.171",
3
+ "version": "2.4.0-next.173",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",