v-sistec-features 1.22.3 → 1.23.2
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/v-sistec-features.css +1 -1
- package/dist/vDataTable.d.ts +16 -0
- package/dist/vDataTable.js +672 -711
- package/package.json +4 -10
- package/src/DatatableVue/components/VColumn.vue +9 -1
- package/src/DatatableVue/components/VDataTable.vue +18 -102
- package/src/DatatableVue/components/VThDataTable.vue +107 -0
- package/src/DatatableVue/keys.ts +2 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "v-sistec-features",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.23.2",
|
|
5
5
|
"author": "Márlon Bento Azevedo (https://github.com/marlon-bento)",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -57,18 +57,12 @@
|
|
|
57
57
|
"vuedraggable": "^4.1.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@
|
|
61
|
-
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
62
|
-
"@semantic-release/exec": "^7.1.0",
|
|
63
|
-
"@semantic-release/git": "^10.0.1",
|
|
64
|
-
"@semantic-release/github": "^11.0.6",
|
|
65
|
-
"@semantic-release/npm": "^12.0.2",
|
|
66
|
-
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
60
|
+
"@release-it/conventional-changelog": "^11.0.1",
|
|
67
61
|
"@types/node": "^24.6.0",
|
|
68
62
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
69
63
|
"@vue/tsconfig": "^0.8.1",
|
|
64
|
+
"release-it": "^20.2.1",
|
|
70
65
|
"sass-embedded": "^1.93.2",
|
|
71
|
-
"semantic-release": "^24.2.9",
|
|
72
66
|
"typescript": "~5.9.3",
|
|
73
67
|
"vite": "^7.1.7",
|
|
74
68
|
"vite-plugin-dts": "^4.5.4",
|
|
@@ -79,7 +73,7 @@
|
|
|
79
73
|
"@tabler/core": "^1.4.0",
|
|
80
74
|
"pinia": "^2.1.0 || ^3.0.0",
|
|
81
75
|
"v-api-fetch": "^1.6.0",
|
|
82
|
-
"v-required": "^2.
|
|
76
|
+
"v-required": "^2.5.0",
|
|
83
77
|
"v3-infinite-loading": "^1.3.2",
|
|
84
78
|
"vue-toastification": "^2.0.0-rc.5"
|
|
85
79
|
}
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
|
-
import { inject, onMounted, useSlots
|
|
6
|
+
import { inject, onMounted, useSlots } from 'vue';
|
|
7
7
|
import { dataTableApiKey } from '../keys';
|
|
8
8
|
|
|
9
9
|
defineSlots<{
|
|
10
10
|
// props para o slot body
|
|
11
11
|
body?: (props: { item: any }) => any,
|
|
12
|
+
col_header?: (props: { col: any, locked: boolean }) => any,
|
|
13
|
+
col_header_midle?: (props: { col: any, locked: boolean }) => any,
|
|
12
14
|
}>();
|
|
13
15
|
interface VColumnProps {
|
|
14
16
|
field?: string | null;
|
|
@@ -113,9 +115,15 @@ onMounted(() => {
|
|
|
113
115
|
class_rules: props.class_rules,
|
|
114
116
|
|
|
115
117
|
bodySlot: slots.body,
|
|
118
|
+
// colHeaderSlot é para o slot do header da coluna, que pode ser usado para colocar ícone de ordenação ou qualquer outra coisa que o usuário queira colocar no header da coluna
|
|
119
|
+
colHeaderSlot: slots.col_header,
|
|
120
|
+
// colHeaderMidleSlot é para o slot do header da coluna, mas ele fica entre o texto do header e o ícone de ordenação, para o usuário colocar coisas entre eles
|
|
121
|
+
colHeaderMidleSlot: slots.col_header_midle,
|
|
116
122
|
...(props.type === 'text' && { limite_text: Number(props.limite_text) }),
|
|
117
123
|
...(props.type === 'img' && { deactivate_img_preview: props.deactivate_img_preview }),
|
|
118
124
|
...(props.type === 'date' && { format: props.format }),
|
|
125
|
+
|
|
119
126
|
});
|
|
127
|
+
|
|
120
128
|
});
|
|
121
129
|
</script>
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
<draggable v-model="draggableColumns" tag="tr" item-key="header" :animation="400"
|
|
76
76
|
ghost-class="ghost-item" drag-class="dragging-item" @start="isDraggingColumns = true"
|
|
77
77
|
@end="() => onDragEnd()">
|
|
78
|
+
|
|
78
79
|
<template #header>
|
|
79
80
|
<th v-if="options.use_expandable_items"></th>
|
|
80
81
|
<th v-if="options.use_checkbox" class="w-1">
|
|
@@ -84,115 +85,27 @@
|
|
|
84
85
|
</template>
|
|
85
86
|
|
|
86
87
|
<template #item="{ element: col }">
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<span @click="() => toggleOrderingState(col.header)" class="ms-2 cursor-pointer">
|
|
93
|
-
<svg v-if="!orderings_state[col.header] || orderings_state[col.header] === 'none'"
|
|
94
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
|
95
|
-
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
96
|
-
<path d="m3 8 4-4 4 4"></path>
|
|
97
|
-
<path d="m11 16-4 4-4-4"></path>
|
|
98
|
-
<path d="M7 4v16"></path>
|
|
99
|
-
<path d="M15 8h6"></path>
|
|
100
|
-
<path d="M15 16h6"></path>
|
|
101
|
-
<path d="M13 12h8"></path>
|
|
102
|
-
</svg>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<svg v-else-if="orderings_state[col.header] === 'decreasing'"
|
|
106
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
|
107
|
-
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
108
|
-
<path d="m3 16 4 4 4-4"></path>
|
|
109
|
-
<path d="M7 20V4"></path>
|
|
110
|
-
<path d="M11 4h10"></path>
|
|
111
|
-
<path d="M11 8h7"></path>
|
|
112
|
-
<path d="M11 12h4"></path>
|
|
113
|
-
</svg>
|
|
114
|
-
|
|
115
|
-
<svg v-else-if="orderings_state[col.header] === 'increasing'"
|
|
116
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
|
117
|
-
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
118
|
-
<path d="m3 8 4-4 4 4"></path>
|
|
119
|
-
<path d="M7 4v16"></path>
|
|
120
|
-
<path d="M11 12h4"></path>
|
|
121
|
-
<path d="M11 16h7"></path>
|
|
122
|
-
<path d="M11 20h10"></path>
|
|
123
|
-
</svg>
|
|
124
|
-
|
|
125
|
-
</span>
|
|
126
|
-
</div>
|
|
127
|
-
|
|
128
|
-
</th>
|
|
129
|
-
</template>
|
|
130
|
-
<template v-else>
|
|
131
|
-
<th class="header-draggable" :class="col.class_column">
|
|
132
|
-
{{ col.header }}
|
|
133
|
-
</th>
|
|
134
|
-
</template>
|
|
135
|
-
|
|
88
|
+
<v-th-data-table :header="col.header" :class_column="col.class_column"
|
|
89
|
+
:use_ordering="col.use_ordering" :orderings_state="orderings_state[col.header] || 'none'"
|
|
90
|
+
@toggleOrderingState="() => toggleOrderingState(col.header)" :locked="false" :col="col">
|
|
91
|
+
|
|
92
|
+
</v-th-data-table>
|
|
136
93
|
</template>
|
|
137
94
|
|
|
138
95
|
<template #footer>
|
|
96
|
+
|
|
139
97
|
<template v-for="col in lockedColumns" :key="col.field || col.header">
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
<span @click="() => toggleOrderingState(col.header)" class="ms-2 cursor-pointer">
|
|
146
|
-
<svg v-if="!orderings_state[col.header] || orderings_state[col.header] === 'none'"
|
|
147
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
|
|
148
|
-
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
149
|
-
stroke-linejoin="round">
|
|
150
|
-
<path d="m3 8 4-4 4 4"></path>
|
|
151
|
-
<path d="m11 16-4 4-4-4"></path>
|
|
152
|
-
<path d="M7 4v16"></path>
|
|
153
|
-
<path d="M15 8h6"></path>
|
|
154
|
-
<path d="M15 16h6"></path>
|
|
155
|
-
<path d="M13 12h8"></path>
|
|
156
|
-
</svg>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
<svg v-else-if="orderings_state[col.header] === 'decreasing'"
|
|
160
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
|
|
161
|
-
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
162
|
-
stroke-linejoin="round">
|
|
163
|
-
<path d="m3 16 4 4 4-4"></path>
|
|
164
|
-
<path d="M7 20V4"></path>
|
|
165
|
-
<path d="M11 4h10"></path>
|
|
166
|
-
<path d="M11 8h7"></path>
|
|
167
|
-
<path d="M11 12h4"></path>
|
|
168
|
-
</svg>
|
|
169
|
-
|
|
170
|
-
<svg v-else-if="orderings_state[col.header] === 'increasing'"
|
|
171
|
-
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
|
|
172
|
-
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
173
|
-
stroke-linejoin="round">
|
|
174
|
-
<path d="m3 8 4-4 4 4"></path>
|
|
175
|
-
<path d="M7 4v16"></path>
|
|
176
|
-
<path d="M11 12h4"></path>
|
|
177
|
-
<path d="M11 16h7"></path>
|
|
178
|
-
<path d="M11 20h10"></path>
|
|
179
|
-
</svg>
|
|
180
|
-
</span>
|
|
181
|
-
</div>
|
|
182
|
-
</th>
|
|
183
|
-
</template>
|
|
184
|
-
|
|
185
|
-
<template v-else>
|
|
186
|
-
<th class="header-locked" :class="col.class_column">
|
|
187
|
-
{{ col.header }}
|
|
188
|
-
</th>
|
|
189
|
-
</template>
|
|
98
|
+
<v-th-data-table :header="col.header" :class_column="col.class_column"
|
|
99
|
+
:use_ordering="col.use_ordering" :orderings_state="orderings_state[col.header] || 'none'"
|
|
100
|
+
@toggleOrderingState="() => toggleOrderingState(col.header)" :col="col" locked>
|
|
101
|
+
|
|
102
|
+
</v-th-data-table>
|
|
190
103
|
|
|
191
104
|
</template>
|
|
192
105
|
</template>
|
|
193
106
|
</draggable>
|
|
194
|
-
|
|
195
107
|
</thead>
|
|
108
|
+
|
|
196
109
|
<tbody>
|
|
197
110
|
<template v-for="(item, index) in items" :key="item[options.item_key]">
|
|
198
111
|
<TransitionGroup tag="tr" :name="isDraggingColumns ? 'column-move' : ''">
|
|
@@ -243,10 +156,10 @@
|
|
|
243
156
|
<span @click="col.click ? col.click(item) : null" v-else-if="col.type === 'date'"
|
|
244
157
|
:class="computeClasses(col, item)">
|
|
245
158
|
<span v-if="col.format === 'complete'">{{ new Date(getSubItem(col.field, item)).toLocaleString()
|
|
246
|
-
|
|
159
|
+
}}</span>
|
|
247
160
|
<span v-if="col.format === 'simple'"> {{ new Date(getSubItem(col.field,
|
|
248
161
|
item)).toLocaleDateString()
|
|
249
|
-
|
|
162
|
+
}} </span>
|
|
250
163
|
</span>
|
|
251
164
|
<div @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
|
|
252
165
|
v-else-if="col.type === 'html'" v-html="getSubItem(col.field, item)">
|
|
@@ -336,6 +249,7 @@ import { useExpandedItem } from '../composables/useExpandedItem';
|
|
|
336
249
|
import { useDataTableFetch } from '../composables/useDataTableFetch';
|
|
337
250
|
import { useCheckBox } from '../composables/useCheckBox.ts';
|
|
338
251
|
import VDataTableLoading from './VDataTableLoading.vue';
|
|
252
|
+
import VThDataTable from './VThDataTable.vue';
|
|
339
253
|
const globalConfig = inject(DATA_TABLE_CONFIG, {});
|
|
340
254
|
const {
|
|
341
255
|
isHovering,
|
|
@@ -532,6 +446,7 @@ function onDragEnd() {
|
|
|
532
446
|
function addColumn(colConfig: ColumnConfiguration): void {
|
|
533
447
|
columns.value.push(colConfig);
|
|
534
448
|
}
|
|
449
|
+
|
|
535
450
|
provide(dataTableApiKey, { addColumn });
|
|
536
451
|
|
|
537
452
|
|
|
@@ -575,6 +490,7 @@ function limiteText(text: string | null, limite: number | null): string | null {
|
|
|
575
490
|
}
|
|
576
491
|
|
|
577
492
|
function toggleOrderingState(header: string) {
|
|
493
|
+
|
|
578
494
|
// desabilita todos que não são o header clicado
|
|
579
495
|
for (const key in orderings_state.value) {
|
|
580
496
|
if (key !== header) {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<th :class="class_all">
|
|
3
|
+
<div :class="{ 'header-ordering': use_ordering }">
|
|
4
|
+
|
|
5
|
+
<component
|
|
6
|
+
v-if="hasCustomHeader"
|
|
7
|
+
:is="col.colHeaderSlot"
|
|
8
|
+
v-bind="{ col: props.col, locked: props.locked }"
|
|
9
|
+
></component>
|
|
10
|
+
|
|
11
|
+
<template v-else>
|
|
12
|
+
<span>
|
|
13
|
+
{{ props.header }}
|
|
14
|
+
</span>
|
|
15
|
+
|
|
16
|
+
<component
|
|
17
|
+
v-if="col.colHeaderMidleSlot"
|
|
18
|
+
:is="col.colHeaderMidleSlot"
|
|
19
|
+
v-bind="{ col: props.col, locked: props.locked }"
|
|
20
|
+
></component>
|
|
21
|
+
|
|
22
|
+
<span v-if="use_ordering" @click="emit('toggleOrderingState')" class="ms-2 cursor-pointer">
|
|
23
|
+
<svg v-if="!props.orderings_state || props.orderings_state === 'none'" xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
25
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
26
|
+
<path d="m3 8 4-4 4 4"></path>
|
|
27
|
+
<path d="m11 16-4 4-4-4"></path>
|
|
28
|
+
<path d="M7 4v16"></path>
|
|
29
|
+
<path d="M15 8h6"></path>
|
|
30
|
+
<path d="M15 16h6"></path>
|
|
31
|
+
<path d="M13 12h8"></path>
|
|
32
|
+
</svg>
|
|
33
|
+
|
|
34
|
+
<svg v-else-if="props.orderings_state === 'decreasing'" xmlns="http://www.w3.org/2000/svg" width="16"
|
|
35
|
+
height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
36
|
+
stroke-linejoin="round">
|
|
37
|
+
<path d="m3 16 4 4 4-4"></path>
|
|
38
|
+
<path d="M7 20V4"></path>
|
|
39
|
+
<path d="M11 4h10"></path>
|
|
40
|
+
<path d="M11 8h7"></path>
|
|
41
|
+
<path d="M11 12h4"></path>
|
|
42
|
+
</svg>
|
|
43
|
+
|
|
44
|
+
<svg v-else-if="props.orderings_state === 'increasing'" xmlns="http://www.w3.org/2000/svg" width="16"
|
|
45
|
+
height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
46
|
+
stroke-linejoin="round">
|
|
47
|
+
<path d="m3 8 4-4 4 4"></path>
|
|
48
|
+
<path d="M7 4v16"></path>
|
|
49
|
+
<path d="M11 12h4"></path>
|
|
50
|
+
<path d="M11 16h7"></path>
|
|
51
|
+
<path d="M11 20h10"></path>
|
|
52
|
+
</svg>
|
|
53
|
+
</span>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
</th>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script setup lang="ts">
|
|
61
|
+
import { computed, Comment, Fragment, Text } from 'vue';
|
|
62
|
+
|
|
63
|
+
const props = defineProps<{
|
|
64
|
+
header: string;
|
|
65
|
+
class_column: string;
|
|
66
|
+
locked: boolean;
|
|
67
|
+
use_ordering: boolean;
|
|
68
|
+
orderings_state: 'none' | 'increasing' | 'decreasing';
|
|
69
|
+
col: any;
|
|
70
|
+
}>();
|
|
71
|
+
|
|
72
|
+
const class_all = computed(() => {
|
|
73
|
+
return {
|
|
74
|
+
'header-draggable': !props.locked,
|
|
75
|
+
'header-locked': props.locked,
|
|
76
|
+
[props.class_column]: true,
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const emit = defineEmits<{
|
|
81
|
+
toggleOrderingState: [void];
|
|
82
|
+
}>();
|
|
83
|
+
|
|
84
|
+
// Função robusta para verificar se todos os nós gerados são apenas comentários (v-if false)
|
|
85
|
+
// para evitar falsos positivos, também verifica se são nós de texto vazios ou apenas espaços em branco, e trata recursivamente fragmentos
|
|
86
|
+
// quando isso for vazio significa que não tem nada no slot então ele mostra a versão padrão do header
|
|
87
|
+
// se tiver algo ele sobrescreve o header padrão
|
|
88
|
+
const isEmptySlot = (vnodes: any[]): boolean => {
|
|
89
|
+
if (!vnodes || vnodes.length === 0) return true;
|
|
90
|
+
return vnodes.every(vnode => {
|
|
91
|
+
if (vnode.type === Comment) return true;
|
|
92
|
+
if (vnode.type === Text && typeof vnode.children === 'string' && !vnode.children.trim()) return true;
|
|
93
|
+
if (vnode.type === Fragment || vnode.type === Symbol.for('v-fgt') || String(vnode.type) === 'Symbol(Fragment)') {
|
|
94
|
+
return isEmptySlot(vnode.children as any[]);
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const hasCustomHeader = computed(() => {
|
|
101
|
+
if (!props.col || !props.col.colHeaderSlot) return false;
|
|
102
|
+
// Executa a função do slot original e analisa a árvore
|
|
103
|
+
const vnodes = props.col.colHeaderSlot({ col: props.col, locked: props.locked });
|
|
104
|
+
return !isEmptySlot(vnodes);
|
|
105
|
+
});
|
|
106
|
+
</script>
|
|
107
|
+
<style scoped></style>
|
package/src/DatatableVue/keys.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface ColumnConfiguration {
|
|
|
10
10
|
class_item: string;
|
|
11
11
|
transform_function: ((value: any) => any) | null;
|
|
12
12
|
bodySlot?: Slot;
|
|
13
|
+
colHeaderSlot?: Slot;
|
|
14
|
+
colHeaderMidleSlot?: Slot;
|
|
13
15
|
limite_text?: number;
|
|
14
16
|
deactivate_img_preview?: boolean;
|
|
15
17
|
format?: 'complete' | 'simple';
|