adminforth 1.5.11-next.1 → 1.5.11

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.
@@ -116,8 +116,12 @@ const options = computed(() => {
116
116
 
117
117
  // for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
118
118
  function mergeOptions(options: any, newOptions: any) {
119
+ if (!newOptions) {
120
+ return;
121
+ }
119
122
  for (const key in newOptions) {
120
- if (typeof newOptions[key] === 'object') {
123
+ // and is not array
124
+ if (typeof newOptions[key] === 'object' && !Array.isArray(newOptions[key])) {
121
125
  if (!options[key]) {
122
126
  options[key] = {};
123
127
  }
@@ -128,8 +128,12 @@ const options = computed(() => {
128
128
 
129
129
  // for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
130
130
  function mergeOptions(options: any, newOptions: any) {
131
+ if (!newOptions) {
132
+ return;
133
+ }
131
134
  for (const key in newOptions) {
132
- if (typeof newOptions[key] === 'object') {
135
+ // and is not array
136
+ if (typeof newOptions[key] === 'object' && !Array.isArray(newOptions[key])) {
133
137
  if (!options[key]) {
134
138
  options[key] = {};
135
139
  }
@@ -42,7 +42,7 @@ const optionsBase = {
42
42
  chart: {
43
43
  height: 400,
44
44
  width: "100%",
45
- type: "donut",
45
+ type: "pie",
46
46
  },
47
47
  stroke: {
48
48
  colors: ["transparent"],
@@ -137,7 +137,8 @@ const options = computed(() => {
137
137
  return;
138
138
  }
139
139
  for (const key in newOptions) {
140
- if (typeof newOptions[key] === 'object') {
140
+ // and is not array
141
+ if (typeof newOptions[key] === 'object' && !Array.isArray(newOptions[key])) {
141
142
  if (!options[key]) {
142
143
  options[key] = {};
143
144
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="relative inline-block afcl-select">
2
+ <div class="relative inline-block afcl-select" ref="internalSelect">
3
3
  <div class="relative">
4
4
  <input
5
5
  ref="inputEl"
@@ -89,7 +89,6 @@ import { ref, computed, onMounted, onUnmounted, watch, type Ref } from 'vue';
89
89
  import { IconCaretDownSolid } from '@iconify-prerendered/vue-flowbite';
90
90
  import { useElementSize } from '@vueuse/core'
91
91
 
92
-
93
92
  const props = defineProps({
94
93
  options: Array,
95
94
  modelValue: {
@@ -123,6 +122,7 @@ const dropdownStyle = ref<{ top?: string; }>({
123
122
  });
124
123
 
125
124
  const selectedItems: Ref<any[]> = ref([]);
125
+ const internalSelect = ref<HTMLElement | null>(null);
126
126
 
127
127
  function inputInput() {
128
128
  if (!props.multiple && selectedItems.value.length) {
@@ -147,15 +147,12 @@ function updateFromProps() {
147
147
  }
148
148
 
149
149
  function inputClick() {
150
- if (props.isReadonly) {
151
- return;
152
- }
153
- if (!showDropdown.value) {
154
- showDropdown.value = true;
155
- } else {
156
- if (!search.value) {
157
- showDropdown.value = false;
158
- }
150
+ if (props.isReadonly) return;
151
+ // Toggle local dropdown
152
+ showDropdown.value = !showDropdown.value;
153
+ // If the dropdown is about to close, reset the search
154
+ if (!showDropdown.value && !search.value) {
155
+ search.value = '';
159
156
  }
160
157
  }
161
158
 
@@ -198,10 +195,12 @@ const filteredItems = computed(() => {
198
195
  );
199
196
  });
200
197
 
201
- const handleClickOutside = (event) => {
202
- if (!event.target.closest('.afcl-select')) {
198
+
199
+ const handleClickOutside = (event: MouseEvent) => {
200
+ const targetEl = event.target as HTMLElement | null;
201
+ const closestSelect = targetEl?.closest('.afcl-select');
202
+ if (closestSelect !== internalSelect.value)
203
203
  showDropdown.value = false;
204
- }
205
204
  };
206
205
 
207
206
  const addClickListener = () => {
@@ -228,7 +227,7 @@ const toogleItem = (item) => {
228
227
  if (!props.multiple && search.value) {
229
228
  search.value = '';
230
229
  }
231
-
230
+
232
231
  const list = selectedItems.value.map(item => item.value);
233
232
  const updValue = list.length ? list : null;
234
233
  let emitValue;
@@ -238,13 +237,10 @@ const toogleItem = (item) => {
238
237
  emitValue = updValue;
239
238
  }
240
239
  emit('update:modelValue', emitValue);
241
-
242
240
  };
243
241
 
244
-
245
242
  onUnmounted(() => {
246
243
  removeClickListener();
247
244
  });
248
245
 
249
-
250
246
  </script>
@@ -0,0 +1,116 @@
1
+ <template>
2
+
3
+ <div class="relative overflow-x-auto shadow-md sm:rounded-lg">
4
+ <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
5
+ <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
6
+ <tr>
7
+ <th scope="col" class="px-6 py-3"
8
+ v-for="column in columns"
9
+ >
10
+ <slot v-if="$slots[`header:${column.fieldName}`]" :name="`header:${column.fieldName}`" :column="column" />
11
+
12
+ <span v-else>
13
+ {{ column.label }}
14
+ </span>
15
+ </th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <tr
20
+ v-for="(item, index) in dataPage"
21
+ :class="{
22
+ 'odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800': evenHighlights,
23
+ 'border-b dark:border-gray-700': index !== dataPage.length - 1 || totalPages > 1,
24
+ }"
25
+ >
26
+ <td class="px-6 py-4"
27
+ v-for="column in props.columns"
28
+ >
29
+ <slot v-if="$slots[`cell:${column.fieldName}`]"
30
+ :name="`cell:${column.fieldName}`"
31
+ :item="item" :column="column"
32
+ >
33
+ </slot>
34
+ <span v-else>
35
+ {{ item[column.fieldName] }}
36
+ </span>
37
+ </td>
38
+ </tr>
39
+ </tbody>
40
+ </table>
41
+ <nav class="flex items-center flex-column flex-wrap md:flex-row justify-between p-4"
42
+ v-if="totalPages > 1"
43
+ :aria-label="$t('Table navigation')">
44
+ <i18n-t
45
+ keypath="Showing {from} to {to} of {total}" tag="span" class="text-sm font-normal text-gray-500 dark:text-gray-400 mb-4 md:mb-0 block w-full md:inline md:w-auto"
46
+ >
47
+ <template #from><span class="font-semibold text-gray-900 dark:text-white">{{ Math.min((currentPage - 1) * props.pageSize + 1, props.data.length) }}</span></template>
48
+ <template #to><span class="font-semibold text-gray-900 dark:text-white">{{ Math.min(currentPage * props.pageSize, props.data.length) }}</span></template>
49
+ <template #total><span class="font-semibold text-gray-900 dark:text-white">{{ props.data.length }}</span></template>
50
+ </i18n-t>
51
+
52
+ <ul class="inline-flex -space-x-px rtl:space-x-reverse text-sm h-8">
53
+ <li v-for="page in totalPages" :key="page">
54
+ <a href="#"
55
+ @click.prevent="switchPage(page)"
56
+ :aria-current="page === page ? 'page' : undefined"
57
+ :class='{
58
+ "text-blue-600 bg-lightPrimary text-lightPrimaryContrast dark:bg-darkPrimary dark:text-darkPrimaryContrast hover:opacity-90": page === currentPage,
59
+ "text-gray-500 border bg-white border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white": page !== currentPage,
60
+ "rounded-s-lg ms-0": page === 1,
61
+ "rounded-e-lg": page === totalPages,
62
+ }'
63
+ class="flex items-center justify-center px-3 h-8 leading-tight ">
64
+ {{ page }}
65
+ </a>
66
+ </li>
67
+ </ul>
68
+ </nav>
69
+ </div>
70
+
71
+
72
+
73
+ </template>
74
+
75
+ <script setup lang="ts">
76
+ import { ref, type Ref, computed } from 'vue';
77
+
78
+ const props = withDefaults(
79
+ defineProps<{
80
+ columns: {
81
+ label: string,
82
+ fieldName: string,
83
+ }[],
84
+ data: {
85
+ [key: string]: any,
86
+ }[],
87
+ evenHighlights?: boolean,
88
+ pageSize?: number,
89
+ }>(), {
90
+ evenHighlights: true,
91
+ pageSize: 10,
92
+ }
93
+ );
94
+
95
+ const currentPage = ref(1);
96
+
97
+ const totalPages = computed(() => {
98
+ return Math.ceil(props.data.length / props.pageSize);
99
+ });
100
+
101
+ const dataPage = computed(() => {
102
+ const start = (currentPage.value - 1) * props.pageSize;
103
+ const end = start + props.pageSize;
104
+ return props.data.slice(start, end);
105
+ });
106
+
107
+ function switchPage(p: number) {
108
+ currentPage.value = p;
109
+ }
110
+
111
+ const emites = defineEmits([
112
+ 'update:activeTab',
113
+ ]);
114
+
115
+
116
+ </script>
@@ -12,4 +12,7 @@ export { default as Dropzone } from './Dropzone.vue';
12
12
  export { default as AreaChart } from './AreaChart.vue';
13
13
  export { default as BarChart } from './BarChart.vue';
14
14
  export { default as PieChart } from './PieChart.vue';
15
+ export { default as Table } from './Table.vue';
16
+
17
+
15
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.5.11-next.1",
3
+ "version": "1.5.11",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",