v-sistec-features 1.2.5 → 1.3.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "v-sistec-features",
3
3
  "private": false,
4
- "version": "1.2.5",
4
+ "version": "1.3.0",
5
5
  "author": "Márlon Bento Azevedo (https://github.com/marlon-bento)",
6
6
  "repository": {
7
7
  "type": "git",
@@ -23,6 +23,10 @@
23
23
  "import": "./dist/vDataTable.js",
24
24
  "types": "./dist/vDataTable.d.ts"
25
25
  },
26
+ "./vDataPage": {
27
+ "import": "./dist/vDataPage.js",
28
+ "types": "./dist/vDataPage.d.ts"
29
+ },
26
30
  "./iframeCommunicator": {
27
31
  "import": "./dist/iframeCommunicator.js",
28
32
  "types": "./dist/iframeCommunicator.d.ts"
@@ -51,17 +55,18 @@
51
55
  "@semantic-release/github": "^11.0.6",
52
56
  "@semantic-release/npm": "^12.0.2",
53
57
  "@semantic-release/release-notes-generator": "^14.1.0",
54
- "semantic-release": "^24.2.9",
55
58
  "@types/node": "^24.6.0",
56
59
  "@vitejs/plugin-vue": "^6.0.1",
57
60
  "@vue/tsconfig": "^0.8.1",
58
61
  "sass-embedded": "^1.93.2",
62
+ "semantic-release": "^24.2.9",
59
63
  "typescript": "~5.9.3",
60
64
  "vite": "^7.1.7",
61
65
  "vue-tsc": "^3.1.0"
62
66
  },
63
67
  "dependencies": {
64
68
  "@tabler/core": "^1.4.0",
65
- "vue": "^3.5.22"
69
+ "v3-infinite-loading": "^1.3.2",
70
+ "vue": "^3.2.0"
66
71
  }
67
72
  }
@@ -0,0 +1,222 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ // =======================================================
5
+ // 1. DEFINIÇÃO DE TIPOS E INTERFACES
6
+ // =======================================================
7
+ interface PaginationObject {
8
+ current_page: number;
9
+ count: number;
10
+ limit_per_page: number;
11
+ }
12
+ interface PaginationProps {
13
+ pagination: PaginationObject;
14
+ filtering?: boolean;
15
+ }
16
+
17
+ // =======================================================
18
+ // 2. PROPS E EMITS
19
+ // =======================================================
20
+ const props = withDefaults(defineProps<PaginationProps>(), {
21
+ filtering: false,
22
+ });
23
+ const emit = defineEmits<{
24
+ (e: 'tradePage'): void
25
+ }>();
26
+
27
+ // =======================================================
28
+ // 3. LÓGICA REATIVA (Computeds e Funções)
29
+ // =======================================================
30
+ const total_pages = computed<number>(() => {
31
+ if (!props.pagination.limit_per_page) return 0;
32
+ return Math.ceil(props.pagination.count / props.pagination.limit_per_page);
33
+ });
34
+
35
+ const next = computed(() => {
36
+ return props.pagination.current_page + 1 < total_pages.value
37
+ ? props.pagination.current_page + 1
38
+ : null;
39
+ });
40
+
41
+ // Funções de navegação
42
+ const nextPage = (): void => {
43
+ props.pagination.current_page++;
44
+ emit("tradePage");
45
+ };
46
+ const setPage = (newPage: number): void => {
47
+ props.pagination.current_page = newPage - 1;
48
+ emit("tradePage");
49
+ };
50
+ const lastPage = (): void => {
51
+ props.pagination.current_page = total_pages.value - 1;
52
+ emit("tradePage");
53
+ };
54
+ const firstPage = (): void => {
55
+ props.pagination.current_page = 0;
56
+ emit("tradePage");
57
+ };
58
+ const prevPage = (): void => {
59
+ if (props.pagination.current_page > 0) {
60
+ props.pagination.current_page--;
61
+ emit("tradePage");
62
+ }
63
+ };
64
+
65
+ // =======================================================
66
+ // 4. LÓGICA DE GERAÇÃO DE PÁGINAS
67
+ // =======================================================
68
+
69
+ /**
70
+ * @description Computa um array com os números das páginas e as reticências a serem exibidas.
71
+ * Ex: [1, 2, '...', 10, 11, 12, '...', 33, 34]
72
+ */
73
+ const paginasParaExibir = computed(() => {
74
+ // Se houver 7 páginas ou menos, mostre todas.
75
+ if (total_pages.value <= 7) {
76
+ return Array.from({ length: total_pages.value }, (_, i) => i + 1);
77
+ }
78
+
79
+ const paginaAtual = props.pagination.current_page + 1;
80
+ const total = total_pages.value;
81
+
82
+ // O conjunto de páginas visíveis sempre inclui as 2 primeiras, 2 últimas,
83
+ // a atual e suas duas vizinhas. O Set cuida de remover duplicatas.
84
+ const paginasEssenciais = new Set([
85
+ 1, 2, // Sempre mostra as 2 primeiras
86
+ paginaAtual - 1, paginaAtual, paginaAtual + 1, // Mostra a atual e vizinhas
87
+ total - 1, total // Sempre mostra as 2 últimas
88
+ ]);
89
+
90
+ const resultado: (number | string)[] = [];
91
+ let ultimoNumeroAdicionado = 0;
92
+
93
+ // Ordena os números e itera sobre eles para inserir as reticências
94
+ Array.from(paginasEssenciais).sort((a, b) => a - b).forEach(num => {
95
+ // Ignora números inválidos (como página 0 ou menores, ou maiores que o total)
96
+ if (num < 1 || num > total) return;
97
+
98
+ // Se houver um buraco entre o último número adicionado e o atual, insere "..."
99
+ if (num > ultimoNumeroAdicionado + 1) {
100
+ resultado.push('...');
101
+ }
102
+
103
+ resultado.push(num);
104
+ ultimoNumeroAdicionado = num;
105
+ });
106
+
107
+
108
+ return resultado;
109
+ });
110
+ const svg_duas_setas =`
111
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
112
+ stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
113
+ class="icon icon-tabler icons-tabler-outline icon-tabler-chevrons-left">
114
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
115
+ <path d="M11 7l-5 5l5 5" />
116
+ <path d="M17 7l-5 5l5 5" />
117
+ </svg>
118
+ `
119
+ const svg_uma_seta = `
120
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
121
+ stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
122
+ class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left">
123
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
124
+ <path d="M15 6l-6 6l6 6" />
125
+ </svg>
126
+ `
127
+
128
+ </script>
129
+
130
+ <template>
131
+ <div class="d-flex align-items-center justify-content-between w-100" v-if="props.pagination.count > 0">
132
+ <span>
133
+ Mostrando de
134
+ {{
135
+ props.pagination.count !== 0
136
+ ? props.pagination.limit_per_page * props.pagination.current_page + 1
137
+ : 0
138
+ }}
139
+ até
140
+ {{
141
+ props.pagination.limit_per_page * (props.pagination.current_page + 1) < props.pagination.count ?
142
+ props.pagination.limit_per_page * (props.pagination.current_page + 1) : props.pagination.count }} de {{
143
+ props.pagination.count }} registros </span>
144
+ <div class="d-flex align-items-center gap-2" v-if="total_pages > 0">
145
+ <div class="d-flex">
146
+ <button class="btn btn-estilo" @click.prevent="firstPage" :disabled="props.pagination.current_page === 0" v-html="svg_duas_setas">
147
+ </button>
148
+ <button class="btn btn-estilo" @click.prevent="prevPage" :disabled="props.pagination.current_page === 0" v-html="svg_uma_seta">
149
+ </button>
150
+ </div>
151
+
152
+ <div class="d-flex gap-2">
153
+ <template v-for="(pagina, index) in paginasParaExibir" :key="index">
154
+ <button v-if="typeof pagina === 'number'"
155
+ :class="props.pagination.current_page + 1 == pagina ? 'page-select' : ''" class="page-estilo"
156
+ @click.prevent="setPage(pagina)" :disabled="props.pagination.current_page + 1 == pagina">
157
+ {{ pagina }}
158
+ </button>
159
+ <span v-else class="m-0 p-0">...</span>
160
+ </template>
161
+ </div>
162
+ <div class="d-flex">
163
+ <button @click.prevent="nextPage" class="btn btn-estilo rotate-180" :disabled="!next" v-html="svg_uma_seta">
164
+ </button>
165
+ <button @click.prevent="lastPage" class="btn btn-estilo rotate-180" :disabled="!next" v-html="svg_duas_setas">
166
+ </button>
167
+ </div>
168
+
169
+ </div>
170
+ </div>
171
+ </template>
172
+ <style lang="scss" scoped>
173
+ .rotate-180 {
174
+ :deep(svg) {
175
+ transform: rotate(180deg);
176
+ }
177
+
178
+ }
179
+ .page-select {
180
+ background-color: var(--tblr-primary) !important;
181
+ color: white !important;
182
+ border: none !important;
183
+ }
184
+
185
+ .page-estilo {
186
+ border: none;
187
+ --cor-escurecida: color-mix(in srgb, var(--tblr-primary), #000 25%);
188
+ //border: 2px solid var(--cor-escurecida);
189
+ background: transparent;
190
+ padding: 1px 10px;
191
+ border-radius: 7px;
192
+ margin: 0 !important;
193
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
194
+
195
+ &:hover {
196
+ background: var(--cor-escurecida);
197
+ color: white;
198
+ }
199
+ }
200
+
201
+ .btn{
202
+ padding: 0 !important;
203
+ margin: 0 !important;
204
+ background: transparent !important;
205
+ border: none !important;
206
+ box-shadow: none !important;
207
+ }
208
+ :deep(.btn-estilo) {
209
+ svg {
210
+ padding: 0px !important;
211
+ margin: 0px !important;
212
+ }
213
+ &:hover svg {
214
+ stroke: var(--tblr-primary);
215
+ }
216
+ }
217
+
218
+ .icon-tabler {
219
+ margin: 0 !important;
220
+ padding: 0 !important;
221
+ }
222
+ </style>