v-sistec-features 1.23.2 → 1.24.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.23.2",
4
+ "version": "1.24.0",
5
5
  "author": "Márlon Bento Azevedo (https://github.com/marlon-bento)",
6
6
  "repository": {
7
7
  "type": "git",
@@ -68,7 +68,7 @@
68
68
  </button>
69
69
  </div>
70
70
  <div class="table-responsive" v-else-if="items">
71
- <div v-if="items.length > 0">
71
+ <div v-if="hasItems || options.show_header_when_empty">
72
72
  <table class="table table-vcenter table-selectable" :class="options.class_table">
73
73
  <thead>
74
74
 
@@ -88,7 +88,7 @@
88
88
  <v-th-data-table :header="col.header" :class_column="col.class_column"
89
89
  :use_ordering="col.use_ordering" :orderings_state="orderings_state[col.header] || 'none'"
90
90
  @toggleOrderingState="() => toggleOrderingState(col.header)" :locked="false" :col="col">
91
-
91
+
92
92
  </v-th-data-table>
93
93
  </template>
94
94
 
@@ -98,7 +98,7 @@
98
98
  <v-th-data-table :header="col.header" :class_column="col.class_column"
99
99
  :use_ordering="col.use_ordering" :orderings_state="orderings_state[col.header] || 'none'"
100
100
  @toggleOrderingState="() => toggleOrderingState(col.header)" :col="col" locked>
101
-
101
+
102
102
  </v-th-data-table>
103
103
 
104
104
  </template>
@@ -107,109 +107,114 @@
107
107
  </thead>
108
108
 
109
109
  <tbody>
110
- <template v-for="(item, index) in items" :key="item[options.item_key]">
111
- <TransitionGroup tag="tr" :name="isDraggingColumns ? 'column-move' : ''">
112
- <td v-if="options.use_expandable_items" class="w-1">
113
- <slot name="expand-button" :item="item" :index="index" :is-expanded="is_item_expanded(item)"
114
- :expand_item_toggle="expand_item_toggle">
115
- <button type="button" class="btn-clean btn-icon-anim"
116
- :class="{ 'is-expanded': is_item_expanded(item) }" @click="expand_item_toggle(item)">
117
-
118
- <template v-if="options.type_button_expand === 'arrow'">
119
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
120
- fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
121
- stroke-linejoin="round"
122
- class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right icon-transition-arrow">
123
- <path stroke="none" d="M0 0h24v24H0z" fill="none" />
124
- <path d="M9 6l6 6l-6 6" />
125
- </svg>
126
-
127
- </template>
128
-
129
- <template v-else>
130
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"
131
- fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
132
- stroke-linejoin="round" class="icon icon-transition-plus">
133
- <path stroke="none" d="M0 0h24v24H0z" fill="none" />
134
- <path d="M12 5l0 14" class="vertical-line" />
135
- <path d="M5 12l14 0" />
136
- </svg>
137
- </template>
138
-
139
- </button>
140
- </slot>
141
- </td>
142
- <td v-if="options.use_checkbox" class="w-1">
143
- <input class="form-check-input m-0" type="checkbox" :checked="isSelected(item)"
144
- @change="toggleItemSelection(item)" aria-label="Selecionar este item" />
145
- </td>
146
-
147
- <td v-for="(col, index) in renderedColumns" :key="col.field || col.header" :class="col.class_row">
148
- <component v-if="col.bodySlot" :is="col.bodySlot" :item="item" :index="index"
149
- :is-selected="isSelected(item)" />
150
- <span @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
151
- v-else-if="col.type === 'text'">
152
- {{
153
- limiteText(getSubItem(col.field, item, col.transform_function), col.limite_text ?? null)
154
- }}</span>
155
-
156
- <span @click="col.click ? col.click(item) : null" v-else-if="col.type === 'date'"
157
- :class="computeClasses(col, item)">
158
- <span v-if="col.format === 'complete'">{{ new Date(getSubItem(col.field, item)).toLocaleString()
159
- }}</span>
160
- <span v-if="col.format === 'simple'"> {{ new Date(getSubItem(col.field,
161
- item)).toLocaleDateString()
162
- }} </span>
163
- </span>
164
- <div @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
165
- v-else-if="col.type === 'html'" v-html="getSubItem(col.field, item)">
166
- </div>
167
-
168
- <div @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
169
- v-else-if="col.type === 'img'">
170
-
171
- <div v-if="getSubItem(col.field, item)" v-bind="col.deactivate_img_preview ? {
172
- class: 'container-img'
173
- } :
174
- {
175
- onMouseover: (event) => handleMouseOver(event, getSubItem(col.field, item)),
176
- onMousemove: handleMouseMove,
177
- onMouseleave: handleMouseLeave,
178
- class: 'container-img container-img-preview'
179
- }">
180
-
181
- <img class="img-tamanho" :src="getSubItem(col.field, item)" />
182
- <img class="img-tamanho-cover" :src="getSubItem(col.field, item)" />
183
- <div class="bg-img"></div>
110
+ <template v-if="hasItems">
111
+ <template v-for="(item, index) in items" :key="item[options.item_key]">
112
+ <TransitionGroup tag="tr" :name="isDraggingColumns ? 'column-move' : ''">
113
+ <td v-if="options.use_expandable_items" class="w-1">
114
+ <slot name="expand-button" :item="item" :index="index" :is-expanded="is_item_expanded(item)"
115
+ :expand_item_toggle="expand_item_toggle">
116
+ <button type="button" class="btn-clean btn-icon-anim"
117
+ :class="{ 'is-expanded': is_item_expanded(item) }" @click="expand_item_toggle(item)">
118
+
119
+ <template v-if="options.type_button_expand === 'arrow'">
120
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
121
+ fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
122
+ stroke-linejoin="round"
123
+ class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right icon-transition-arrow">
124
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
125
+ <path d="M9 6l6 6l-6 6" />
126
+ </svg>
127
+
128
+ </template>
129
+
130
+ <template v-else>
131
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"
132
+ fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
133
+ stroke-linejoin="round" class="icon icon-transition-plus">
134
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
135
+ <path d="M12 5l0 14" class="vertical-line" />
136
+ <path d="M5 12l14 0" />
137
+ </svg>
138
+ </template>
139
+
140
+ </button>
141
+ </slot>
142
+ </td>
143
+ <td v-if="options.use_checkbox" class="w-1">
144
+ <input class="form-check-input m-0" type="checkbox" :checked="isSelected(item)"
145
+ @change="toggleItemSelection(item)" aria-label="Selecionar este item" />
146
+ </td>
147
+
148
+ <td v-for="(col, index) in renderedColumns" :key="col.field || col.header" :class="col.class_row">
149
+ <component v-if="col.bodySlot" :is="col.bodySlot" :item="item" :index="index"
150
+ :is-selected="isSelected(item)" />
151
+ <span @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
152
+ v-else-if="col.type === 'text'">
153
+ {{
154
+ limiteText(getSubItem(col.field, item, col.transform_function), col.limite_text ?? null)
155
+ }}</span>
156
+
157
+ <span @click="col.click ? col.click(item) : null" v-else-if="col.type === 'date'"
158
+ :class="computeClasses(col, item)">
159
+ <span v-if="col.format === 'complete'">{{ new Date(getSubItem(col.field,
160
+ item)).toLocaleString()
161
+ }}</span>
162
+ <span v-if="col.format === 'simple'"> {{ new Date(getSubItem(col.field,
163
+ item)).toLocaleDateString()
164
+ }} </span>
165
+ </span>
166
+ <div @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
167
+ v-else-if="col.type === 'html'" v-html="getSubItem(col.field, item)">
184
168
  </div>
185
169
 
186
- </div>
187
- <span class="text-danger erro-custom-container" v-else>tipo <span
188
- class="badge bg-orange text-white erro-custom-text">{{ col.type }}</span> não suportado</span>
189
- </td>
190
- </TransitionGroup>
191
- <Transition :name="'expand-item-' + options.type_animation_expand"
192
- :css="!options.deactivate_animation_expand">
193
- <!-- mostra uma linha após cada item -->
194
- <tr :id="'expand-item-' + item[options.item_key]" v-if="is_item_expanded(item)"
195
- class="expanded-item-row">
196
- <!-- se estiver usando checkbox existe uma coluna a mais -->
197
- <td :colspan="colspanExpandItems()">
198
- <slot name="after-row" :item="item">
170
+ <div @click="col.click ? col.click(item) : null" :class="computeClasses(col, item)"
171
+ v-else-if="col.type === 'img'">
199
172
 
200
- </slot>
173
+ <div v-if="getSubItem(col.field, item)" v-bind="col.deactivate_img_preview ? {
174
+ class: 'container-img'
175
+ } :
176
+ {
177
+ onMouseover: (event) => handleMouseOver(event, getSubItem(col.field, item)),
178
+ onMousemove: handleMouseMove,
179
+ onMouseleave: handleMouseLeave,
180
+ class: 'container-img container-img-preview'
181
+ }">
182
+
183
+ <img class="img-tamanho" :src="getSubItem(col.field, item)" />
184
+ <img class="img-tamanho-cover" :src="getSubItem(col.field, item)" />
185
+ <div class="bg-img"></div>
186
+ </div>
201
187
 
188
+ </div>
189
+ <span class="text-danger erro-custom-container" v-else>tipo <span
190
+ class="badge bg-orange text-white erro-custom-text">{{ col.type }}</span> não
191
+ suportado</span>
202
192
  </td>
203
- </tr>
204
- </Transition>
193
+ </TransitionGroup>
194
+ <Transition :name="'expand-item-' + options.type_animation_expand"
195
+ :css="!options.deactivate_animation_expand">
196
+ <!-- mostra uma linha após cada item -->
197
+ <tr :id="'expand-item-' + item[options.item_key]" v-if="is_item_expanded(item)"
198
+ class="expanded-item-row">
199
+ <!-- se estiver usando checkbox existe uma coluna a mais -->
200
+ <td :colspan="colspanExpandItems()">
201
+ <slot name="after-row" :item="item">
202
+
203
+ </slot>
205
204
 
205
+ </td>
206
+ </tr>
207
+ </Transition>
206
208
 
209
+
210
+ </template>
207
211
  </template>
208
212
 
213
+
209
214
  </tbody>
210
215
  </table>
211
216
  </div>
212
- <div v-else-if="first_fetch === false">
217
+ <div v-if="!hasItems && first_fetch === false">
213
218
  <slot name="idle-state">
214
219
 
215
220
  </slot>
@@ -288,6 +293,7 @@ const props = withDefaults(defineProps<VDataTableProps>(), {
288
293
  disable_search: false,
289
294
  pagination_teleport: null,
290
295
  search_teleport: null,
296
+ show_header_when_empty: false,
291
297
  });
292
298
  const options = computed(() => {
293
299
  return {
@@ -326,6 +332,7 @@ const options = computed(() => {
326
332
  min_loading_delay: props.min_loading_delay ?? globalConfig.min_loading_delay ?? 600,
327
333
  retry_attempts: props.retry_attempts ?? globalConfig.retry_attempts ?? 3,
328
334
  retry_delay: props.retry_delay ?? globalConfig.retry_delay ?? 2000,
335
+ show_header_when_empty: props.show_header_when_empty ?? globalConfig.show_header_when_empty ?? false,
329
336
  };
330
337
  });
331
338
  const emit = defineEmits(['tradePage', 'beforeFetch', 'afterFetch', 'clickedClearSearch']);
@@ -411,8 +418,10 @@ const item_use = computed<number[]>(() => {
411
418
  return use;
412
419
  });
413
420
 
414
-
415
-
421
+ //tem pelo menos um item
422
+ const hasItems = computed(() => {
423
+ return items.value.length > 0
424
+ });
416
425
 
417
426
 
418
427
  // =======================================================
@@ -608,258 +617,5 @@ watch(
608
617
  </script>
609
618
 
610
619
  <style lang="scss" scoped>
611
- .table-responsive {
612
- overflow-x: auto;
613
- }
614
-
615
- .state-feedback {
616
- padding: 1rem;
617
- text-align: center;
618
- }
619
-
620
- .state-feedback.error {
621
- color: red;
622
- }
623
-
624
- .pagination-controls {
625
- margin-top: 1rem;
626
- display: flex;
627
- justify-content: space-between;
628
- }
629
-
630
- $max-width-img: 40px;
631
-
632
-
633
- .container-img {
634
- aspect-ratio: 1;
635
- display: flex;
636
- justify-content: center;
637
- overflow: hidden;
638
- position: relative;
639
- max-width: $max-width-img;
640
- min-width: $max-width-img;
641
-
642
- .img-tamanho-cover {
643
- position: absolute;
644
- top: 0;
645
- width: 100%;
646
- height: 100%;
647
- object-fit: cover;
648
- z-index: 0;
649
- opacity: 0.5;
650
- filter: blur(4px);
651
- }
652
-
653
- .img-tamanho {
654
- object-fit: contain;
655
- width: 100%;
656
- height: 100%;
657
- z-index: 2;
658
- }
659
-
660
- &.container-img-preview {
661
- cursor: pointer;
662
-
663
- &:hover {
664
- border-style: dashed;
665
- border-color: var(--tblr-primary);
666
- border-width: 2px;
667
- transition: border-width 0.15s ease-in-out;
668
-
669
- .img-tamanho {
670
- opacity: 0.3;
671
- }
672
- }
673
- }
674
- }
675
-
676
- .bg-img {
677
- background-color: #0000004d;
678
- position: absolute;
679
- top: 0;
680
- width: 100%;
681
- height: 100%;
682
- z-index: 1;
683
- }
684
-
685
- $max-width-preview: 250px;
686
-
687
- .image-preview-container {
688
- position: fixed;
689
-
690
- z-index: 9999;
691
-
692
- background-color: #fff;
693
- border-radius: 8px;
694
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
695
- padding: 5px;
696
-
697
- pointer-events: none;
698
- transition: opacity 0.2s ease-in-out;
699
-
700
- .image-preview-large {
701
- display: block;
702
- max-width: $max-width-preview;
703
-
704
- max-height: $max-width-preview;
705
- border-radius: 4px;
706
- }
707
- }
708
-
709
- .form-check-input {
710
- border-width: 1px !important;
711
- border-color: rgba(0, 0, 0, 0.391) !important;
712
- width: 17px;
713
- height: 17px;
714
- }
715
-
716
- [data-bs-theme=dark] .form-check-input {
717
- border-color: rgba(255, 255, 255, 0.374) !important;
718
- }
719
-
720
-
721
-
722
- /*
723
- Estilos para arrastar e soltar colunas
724
- */
725
-
726
- .ghost-item {
727
- opacity: 0.5;
728
- background: var(--tblr-primary-lt, #e6f0ff);
729
- border-radius: 8px;
730
- }
731
-
732
- .dragging-item {
733
- cursor: grabbing;
734
- background: var(--tblr-primary);
735
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
736
- opacity: 0.5;
737
- background-color: var(--tblr-primary-bg-subtle);
738
- filter: grayscale(0) invert(0);
739
- }
740
-
741
- .header-draggable {
742
- cursor: grab;
743
- }
744
-
745
-
746
- /*
747
- Animações para movimentação de colunas
748
- */
749
- .column-move-move {
750
- transition: transform 0.4s ease;
751
- }
752
-
753
- .column-move-enter-active,
754
- .column-move-leave-active {
755
- transition: all 0.4s ease;
756
- }
757
-
758
-
759
- .header-ordering {
760
- display: flex;
761
- justify-content: space-between;
762
- }
763
-
764
-
765
-
766
-
767
-
768
-
769
-
770
-
771
-
772
-
773
- /* 1. Animação de entrada para novos itens */
774
- .expand-item-expand-enter-active {
775
- transition: all 0.5s ease;
776
- }
777
-
778
- .expand-item-expand-enter-from {
779
- opacity: 0;
780
- transform: scaleY(0.3) translateY(-30px);
781
- /* Começa em cima e desce */
782
- }
783
-
784
- .expand-item-expand-enter-to {
785
- opacity: 1;
786
- transform: scaleY(1);
787
- transform: translateY(0);
788
- }
789
-
790
- /* 2. Animação de saída para itens removidos*/
791
- .expand-item-expand-leave-active {
792
- transition: all 0.4s ease;
793
- }
794
-
795
- .expand-item-expand-leave-to {
796
- opacity: 0;
797
- transform: scaleY(0.3) translateY(-30px);
798
- /* Desliza para cima e desaparece */
799
- }
800
-
801
-
802
-
803
- .expand-item-fade-enter-active,
804
- .expand-item-fade-leave-active {
805
- transition: opacity 0.5s ease;
806
- }
807
-
808
- .expand-item-fade-enter-from,
809
- .expand-item-fade-leave-to {
810
- opacity: 0;
811
- }
812
-
813
-
814
-
815
-
816
-
817
- .btn-clean {
818
- display: inline-flex;
819
- align-items: center;
820
- justify-content: center;
821
- padding: 4px;
822
- border-radius: 4px;
823
- transition: background-color 0.2s ease;
824
- background: transparent;
825
- border: none;
826
- outline: none;
827
- cursor: pointer;
828
-
829
-
830
- &:hover {
831
- background-color: rgba(0, 0, 0, 0.05);
832
- }
833
- }
834
-
835
-
836
- .icon-transition-arrow {
837
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s ease;
838
- color: var(--tblr-primary, #206bc4);
839
- }
840
-
841
-
842
- .is-expanded .icon-transition-arrow {
843
- transform: rotate(90deg);
844
- }
845
-
846
-
847
- .icon-transition-plus {
848
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s ease;
849
- color: var(--tblr-primary, #206bc4);
850
- }
851
-
852
- .icon-transition-plus .vertical-line {
853
- transform-origin: center;
854
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease;
855
- }
856
-
857
- .is-expanded .icon-transition-plus {
858
- transform: rotate(180deg);
859
- }
860
-
861
- .is-expanded .icon-transition-plus .vertical-line {
862
- transform: scaleY(0);
863
- opacity: 0;
864
- }
620
+ @use '@/DatatableVue/style/scss/VDataTable.scss';
865
621
  </style>