@zeedhi/vuetify 3.1.0 → 3.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.
Files changed (89) hide show
  1. package/dist/zd-vuetify.css +30 -19
  2. package/dist/zd-vuetify.min.css +2 -2
  3. package/dist/zd-vuetify.min.js +15 -17
  4. package/dist/zd-vuetify.mjs +678 -368
  5. package/package.json +3 -3
  6. package/src/components/zd-checkbox/ZdCheckbox.vue +4 -0
  7. package/src/components/zd-component/ZdComponent.ts +15 -13
  8. package/src/components/zd-date-input/ZdDateInput.ts +1 -0
  9. package/src/components/zd-grid-editable/ZdGridEditable.ts +16 -13
  10. package/src/components/zd-select/ZdSelect.ts +18 -1
  11. package/src/components/zd-select/ZdSelect.vue +3 -2
  12. package/src/components/zd-select-multiple/ZdSelectMultiple.ts +21 -3
  13. package/src/components/zd-select-multiple/ZdSelectMultiple.vue +10 -1
  14. package/src/components/zd-tabs/ZdTab.ts +40 -6
  15. package/src/components/zd-tabs/ZdTab.vue +16 -3
  16. package/src/components/zd-tabs/ZdTabItem.ts +2 -2
  17. package/src/components/zd-tabs/ZdTabItem.vue +3 -1
  18. package/src/components/zd-tabs/ZdTabs.ts +96 -2
  19. package/src/components/zd-tabs/ZdTabs.vue +46 -17
  20. package/src/components/zd-text-input/ZdTextInput.ts +6 -0
  21. package/src/components/zd-text-input/ZdTextInput.vue +1 -1
  22. package/src/components/zd-textarea/ZdTextarea.vue +1 -0
  23. package/src/components/zd-tooltip/ZdTooltip.vue +2 -1
  24. package/src/composables/gridColumns.ts +11 -6
  25. package/types/components/zd-alert/ZdAlert.d.ts +299 -299
  26. package/types/components/zd-badge/ZdBadge.d.ts +159 -159
  27. package/types/components/zd-breadcrumbs/ZdBreadcrumbs.d.ts +168 -168
  28. package/types/components/zd-button/ZdButton.d.ts +159 -159
  29. package/types/components/zd-button-group/ZdButtonGroup.d.ts +168 -168
  30. package/types/components/zd-card/ZdCard.d.ts +159 -159
  31. package/types/components/zd-carousel/ZdCarousel.d.ts +476 -476
  32. package/types/components/zd-checkbox-multiple/ZdCheckboxMultiple.d.ts +599 -599
  33. package/types/components/zd-chip/ZdChip.d.ts +159 -159
  34. package/types/components/zd-code-viewer/ZdCodeViewer.d.ts +168 -168
  35. package/types/components/zd-col/ZdCol.d.ts +168 -168
  36. package/types/components/zd-collapse-card/ZdCollapseCard.d.ts +374 -374
  37. package/types/components/zd-container/ZdContainer.d.ts +168 -168
  38. package/types/components/zd-currency/ZdCurrency.d.ts +595 -595
  39. package/types/components/zd-date-range/ZdDateRange.d.ts +600 -597
  40. package/types/components/zd-divider/ZdDivider.d.ts +168 -168
  41. package/types/components/zd-dropdown/ZdDropdown.d.ts +252 -252
  42. package/types/components/zd-footer/ZdFooter.d.ts +420 -420
  43. package/types/components/zd-frame-page/ZdFramePage.d.ts +160 -160
  44. package/types/components/zd-grid/ZdGrid.d.ts +2976 -2976
  45. package/types/components/zd-grid/composables/grid-instance.d.ts +1351 -1351
  46. package/types/components/zd-grid/footer/ZdGridFooter.d.ts +1351 -1351
  47. package/types/components/zd-grid/toolbar/ZdGridToolbar.d.ts +1351 -1351
  48. package/types/components/zd-grid-editable/ZdGridEditable.d.ts +2977 -2979
  49. package/types/components/zd-grid-editable/cell/ZdGridEditableCell.d.ts +271 -271
  50. package/types/components/zd-header/ZdHeader.d.ts +412 -412
  51. package/types/components/zd-image/ZdImage.d.ts +168 -168
  52. package/types/components/zd-increment/ZdIncrement.d.ts +595 -595
  53. package/types/components/zd-iterable/ZdIterableNoData.d.ts +1351 -1351
  54. package/types/components/zd-iterable/zd-iterable-columns-button/ZdIterableColumnsButton.d.ts +472 -472
  55. package/types/components/zd-iterable/zd-iterable-page-info/ZdIterablePageInfo.d.ts +481 -481
  56. package/types/components/zd-iterable/zd-iterable-page-size/ZdIterablePageSize.d.ts +1080 -1080
  57. package/types/components/zd-iterable/zd-iterable-pagination/ZdIterablePagination.d.ts +481 -481
  58. package/types/components/zd-iterable-component-render/ZdIterableComponentRender.d.ts +816 -816
  59. package/types/components/zd-layout/ZdLayout.d.ts +168 -168
  60. package/types/components/zd-list/ZdList.d.ts +447 -447
  61. package/types/components/zd-list/ZdListGroup.d.ts +560 -560
  62. package/types/components/zd-list/ZdListItem.d.ts +280 -280
  63. package/types/components/zd-login/ZdLogin.d.ts +336 -336
  64. package/types/components/zd-login/ZdLoginButton.d.ts +526 -526
  65. package/types/components/zd-main/ZdMain.d.ts +168 -168
  66. package/types/components/zd-master-detail/ZdMasterDetail.d.ts +167 -167
  67. package/types/components/zd-menu/ZdMenu.d.ts +3060 -1068
  68. package/types/components/zd-menu/ZdMenuButton.d.ts +159 -159
  69. package/types/components/zd-menu/ZdMenuGroup.d.ts +5205 -1000
  70. package/types/components/zd-menu/ZdMenuLink.d.ts +8943 -1529
  71. package/types/components/zd-menu/ZdMenuSeparator.d.ts +168 -168
  72. package/types/components/zd-modal/ZdModalCloseButton.d.ts +159 -159
  73. package/types/components/zd-month/ZdMonth.d.ts +598 -597
  74. package/types/components/zd-number-input/ZdNumberInput.d.ts +596 -596
  75. package/types/components/zd-password/ZdPassword.d.ts +595 -595
  76. package/types/components/zd-progress/ZdProgress.d.ts +252 -252
  77. package/types/components/zd-row/ZdRow.d.ts +168 -168
  78. package/types/components/zd-switch/ZdSwitch.d.ts +595 -595
  79. package/types/components/zd-table/ZdTable.d.ts +313 -313
  80. package/types/components/zd-tabs/ZdTab.d.ts +144 -150
  81. package/types/components/zd-tabs/ZdTabItem.d.ts +6 -6
  82. package/types/components/zd-tabs/ZdTabs.d.ts +330 -311
  83. package/types/components/zd-tag/ZdTag.d.ts +168 -168
  84. package/types/components/zd-text/ZdText.d.ts +168 -168
  85. package/types/components/zd-time/ZdTime.d.ts +595 -595
  86. package/types/components/zd-tooltip/ZdTooltip.d.ts +168 -168
  87. package/types/components/zd-tree/ZdTree.d.ts +591 -591
  88. package/types/components/zd-tree-grid/ZdTreeGrid.d.ts +1485 -1485
  89. package/types/composables/gridColumns.d.ts +140 -140
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeedhi/vuetify",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Zeedhi Components based on Vuetify",
5
5
  "author": "Zeedhi <zeedhi@teknisa.com>",
6
6
  "license": "ISC",
@@ -42,7 +42,7 @@
42
42
  "@vitest/coverage-v8": "^2.1.3",
43
43
  "@zeedhi/common": "^3.0.0",
44
44
  "@zeedhi/core": "^3.0.0",
45
- "@zeedhi/vue": "^3.1.0",
45
+ "@zeedhi/vue": "^3.3.0",
46
46
  "vue": "^3.0.0",
47
47
  "vue-router": "^4.2.2",
48
48
  "vuetify": "^3.11.0"
@@ -58,5 +58,5 @@
58
58
  "env": {
59
59
  "NODE_ENV": "production"
60
60
  },
61
- "gitHead": "adbb8c173143730e93a0c76804ffb53e608a9fdb"
61
+ "gitHead": "3398ef763d8812e5b8feb5b8f06db1b377271fde"
62
62
  }
@@ -42,6 +42,10 @@
42
42
  .zd-checkbox {
43
43
  &.v-input {
44
44
  height: fit-content;
45
+
46
+ .v-selection-control {
47
+ min-height: 28px !important;
48
+ }
45
49
  }
46
50
 
47
51
  .v-label {
@@ -235,7 +235,7 @@ export function useCreateInstance<T extends Component, G extends RootRef = RootR
235
235
  explicitlyPassedProps[key] = props[key];
236
236
  }
237
237
  }
238
- explicitlyPassedProps.instanceObj = undefined;
238
+ delete explicitlyPassedProps.instanceObject;
239
239
 
240
240
  const events = getInstanceEvents([props.events, props.instanceObject.events]);
241
241
 
@@ -267,18 +267,20 @@ export function useCreateInstance<T extends Component, G extends RootRef = RootR
267
267
  const instance = reactive(instanceObj);
268
268
 
269
269
  // criar reatividades nas propriedades. (PropWatch)
270
- Object.keys(props).forEach((key: string) => {
271
- if (!(key in instance)) return;
272
- if (typeof props[key] === 'function') return;
273
- if (propsDefs[key] && !propsDefs[key].watch) return;
274
-
275
- watch(
276
- () => props[key],
277
- (value) => {
278
- (instance as any)[key] = value;
279
- }
280
- );
281
- });
270
+ if (!createdFromObject) {
271
+ Object.keys(props).forEach((key: string) => {
272
+ if (!(key in instance)) return;
273
+ if (typeof props[key] === 'function') return;
274
+ if (propsDefs[key]?.watch === false) return;
275
+
276
+ watch(
277
+ () => props[key],
278
+ value => {
279
+ (instance as any)[key] = value;
280
+ },
281
+ );
282
+ });
283
+ }
282
284
 
283
285
  addChild({ instance, props });
284
286
 
@@ -118,6 +118,7 @@ const dateInputComponent = defineComponent({
118
118
  instance.showDatePicker = false;
119
119
  }
120
120
  instance.validate();
121
+ instance.change();
121
122
  };
122
123
 
123
124
  const helperValuesOptionClick = (helper: string) => {
@@ -16,6 +16,7 @@ import { RowNotFoundError } from '../../errors';
16
16
  import { buildProps } from '../../utils';
17
17
  import { getRootElement, useCreateInstance } from '../zd-component/ZdComponent';
18
18
  import { ZdGridProps, useGridInstance } from '../zd-grid/ZdGrid';
19
+ import debounce from 'lodash.debounce';
19
20
 
20
21
  export const ZdGridEditableProps = buildProps({
21
22
  ...ZdGridProps,
@@ -89,22 +90,24 @@ export function useGridEditableInstance({
89
90
  const key = instance.getRowKey(row);
90
91
  editingCell.value = { key, column: column.name };
91
92
 
92
- setTimeout(() => {
93
- const key = instance.getRowKey(row);
93
+ checkToggleComponent(row, column);
94
+ };
94
95
 
95
- try {
96
- const component = instance.getComponent<Input>(String(key), column.name);
97
- component?.setFocus();
96
+ const checkToggleComponent = debounce((row: IDictionary, column: GridColumnEditable) => {
97
+ const key = instance.getRowKey(row);
98
98
 
99
- if (component instanceof Toggleable) {
100
- component.toggleValue();
101
- component.change();
102
- }
103
- } catch (e) {
104
- if (!(e instanceof InstanceNotFoundError)) throw e;
99
+ try {
100
+ const component = instance.getComponent<Input>(String(key), column.name);
101
+ component?.setFocus();
102
+
103
+ if (component instanceof Toggleable) {
104
+ component.toggleValue();
105
+ component.change();
105
106
  }
106
- });
107
- };
107
+ } catch (e) {
108
+ if (!(e instanceof InstanceNotFoundError)) throw e;
109
+ }
110
+ });
108
111
 
109
112
  const viewEnterEdit = (key: string, columnName: string) => {
110
113
  editingCell.value = { key, column: columnName };
@@ -1,6 +1,14 @@
1
1
  import { Select } from '@zeedhi/common';
2
2
  import { FormatterParserProvider, IDictionary } from '@zeedhi/core';
3
- import { ComponentPublicInstance, Ref, SetupContext, UnwrapNestedRefs, computed, defineComponent, useSlots } from 'vue';
3
+ import {
4
+ ComponentPublicInstance,
5
+ Ref,
6
+ SetupContext,
7
+ UnwrapNestedRefs,
8
+ computed,
9
+ defineComponent,
10
+ useSlots,
11
+ } from 'vue';
4
12
  import { useDensity } from '../../composables';
5
13
  import { buildProps } from '../../utils';
6
14
  import { getRootElement } from '../zd-component/ZdComponent';
@@ -192,6 +200,14 @@ export function useSelect<TG extends Select>(
192
200
  instance.keydown(event, rootElement.value);
193
201
  };
194
202
 
203
+ const selectClear = () => {
204
+ // trigger input for non-autocomplete selects
205
+ // it is already automatically triggered for autocomplete selects
206
+ if (!instance.autocomplete) {
207
+ textInputScope.input();
208
+ }
209
+ };
210
+
195
211
  const autoSelectFirst = computed(() => instance.autoSelection && items.value.length === 1);
196
212
 
197
213
  const menuClass = computed(() => {
@@ -222,6 +238,7 @@ export function useSelect<TG extends Select>(
222
238
  selectChange,
223
239
  selectInput,
224
240
  selectKeydown,
241
+ selectClear,
225
242
  hasItemBeforeSlot,
226
243
  hasItemAfterSlot,
227
244
  onLoadMoreIntersect,
@@ -74,6 +74,7 @@
74
74
  @mouseleave="mouseleave($event)"
75
75
  @click="click($event)"
76
76
  @update:modelValue="selectChange($event)"
77
+ @click:clear="selectClear()"
77
78
  @blur="blur($event)"
78
79
  @focus="focus($event)"
79
80
  @update:search="selectInput($event)"
@@ -178,7 +179,7 @@
178
179
  min-height: 22px;
179
180
  padding: 0;
180
181
  }
181
-
182
+
182
183
  .v-field__input {
183
184
  padding: 0;
184
185
  min-height: 34px;
@@ -207,4 +208,4 @@
207
208
  }
208
209
  }
209
210
  }
210
- </style>
211
+ </style>
@@ -6,6 +6,7 @@ import { buildProps } from '../../utils';
6
6
  import { getRootElement } from '../zd-component/ZdComponent';
7
7
  import { useCreateInputInstance } from '../zd-input/ZdInput';
8
8
  import { ZdSelectProps, useSelect } from '../zd-select/ZdSelect';
9
+ import { ListItem } from 'vuetify/lib/composables/list-items';
9
10
 
10
11
  /**
11
12
  * Select Multiple component
@@ -330,12 +331,12 @@ const selectMultipleComponent: any = defineComponent({
330
331
  return selectFormatterFn(item, formatterProps);
331
332
  };
332
333
 
333
- const removeItem = (item: IDictionary<any>) => {
334
+ const removeItem = (item: ListItem<any>) => {
334
335
  const rootValue = root.value as VSelect;
335
- rootValue.select(item.value, false);
336
+ rootValue.select(item, false);
336
337
  };
337
338
 
338
- const selectChange = (value: any, event: Event) => {
339
+ const selectChange = (value: any[], event?: Event) => {
339
340
  const input = getRootElement(root);
340
341
 
341
342
  instance.selectChange(
@@ -345,6 +346,22 @@ const selectMultipleComponent: any = defineComponent({
345
346
  );
346
347
  };
347
348
 
349
+ const selectClear = () => {
350
+ const input = getRootElement(root);
351
+ const hasSelectedValue = Array.isArray(instance.value) && instance.value.length > 0;
352
+ const hasSearchText = !!instance.search;
353
+
354
+ if (hasSelectedValue) {
355
+ instance.selectChange([], undefined, input.value);
356
+ }
357
+
358
+ if (hasSearchText) {
359
+ selectScope.selectInput('');
360
+ } else {
361
+ instance.search = '';
362
+ }
363
+ };
364
+
348
365
  let observer: ResizeObserver | undefined;
349
366
 
350
367
  onMounted(() => {
@@ -381,6 +398,7 @@ const selectMultipleComponent: any = defineComponent({
381
398
  selectClick,
382
399
  selectBlur,
383
400
  selectChange,
401
+ selectClear,
384
402
  formattedDataDiscreteText,
385
403
  ajustSize,
386
404
  onLoadMoreIntersect,
@@ -80,6 +80,15 @@
80
80
  @keydown="instance.keydown($event)"
81
81
  v-on="getIconClickEvents()"
82
82
  >
83
+ <template #clear="{ props }">
84
+ <v-icon
85
+ :tabindex="props.tabindex"
86
+ @focus="props.onFocus"
87
+ @blur="props.onBlur"
88
+ @click="selectClear"
89
+ ></v-icon>
90
+ </template>
91
+
83
92
  <template #prepend-item v-if="instance.itemBeforeSlot.length || instance.showSelectAll">
84
93
  <template v-if="instance.showSelectAll">
85
94
  <v-list-item
@@ -297,4 +306,4 @@
297
306
  .zd-select__menu .v-list-item-title, .zd-select__menu .v-list-item__content {
298
307
  font-size: var(--zd-font-body1-size);
299
308
  }
300
- </style>
309
+ </style>
@@ -1,6 +1,6 @@
1
- import { Tab } from '@zeedhi/common';
1
+ import { Tab, Tabs } from '@zeedhi/common';
2
2
  import { Event } from '@zeedhi/core';
3
- import { defineComponent } from 'vue';
3
+ import { computed, defineComponent, ref } from 'vue';
4
4
  import { useDensity } from '../../composables';
5
5
  import { buildProps } from '../../utils';
6
6
  import { useCreateInstance, useGetMethods } from '../zd-component/ZdComponent';
@@ -15,9 +15,6 @@ export const ZdTabProps = buildProps({
15
15
  tabTitle: {
16
16
  type: [String],
17
17
  },
18
- tabName: {
19
- type: [String],
20
- },
21
18
  color: {
22
19
  type: [String],
23
20
  default: 'primary',
@@ -70,6 +67,8 @@ const tabComponent = defineComponent({
70
67
 
71
68
  const { click, focus, blur, mouseenter, mouseleave } = useGetMethods(instance, root);
72
69
 
70
+ const isDragging = ref<boolean>(false);
71
+
73
72
  const clickTab = (event: Event) => {
74
73
  ctx.emit('click', event);
75
74
  };
@@ -78,9 +77,43 @@ const tabComponent = defineComponent({
78
77
  ctx.emit('keydown', event);
79
78
  };
80
79
 
80
+ const sortable = computed(() => {
81
+ return (instance.parent as Tabs)?.sortable;
82
+ })
83
+
84
+ const handleDragStart = (event: DragEvent): void => {
85
+ if (!sortable.value) {
86
+ event.preventDefault();
87
+ return;
88
+ }
89
+
90
+ if (event.dataTransfer) {
91
+ event.dataTransfer.effectAllowed = 'move';
92
+
93
+ // Compatibilidade Firefox
94
+ event.dataTransfer.setData('text/plain', '');
95
+
96
+ const tabsInstance = instance.parent as Tabs;
97
+ const sourceIndex = tabsInstance.tabs.findIndex((tab) => tab.name === instance.name);
98
+
99
+ event.dataTransfer.setData(`application/x-zd-tabs-owner-${tabsInstance.name.toLowerCase()}`, '');
100
+ event.dataTransfer.setData('application/x-zd-tab-index', String(sourceIndex));
101
+ }
102
+
103
+ isDragging.value = true;
104
+
105
+ event.stopPropagation();
106
+ };
107
+
108
+ const handleDragEnd = (): void => {
109
+ isDragging.value = false;
110
+ };
111
+
81
112
  return {
82
113
  instance,
83
114
  root,
115
+ density,
116
+ sortable,
84
117
  click,
85
118
  focus,
86
119
  blur,
@@ -89,7 +122,8 @@ const tabComponent = defineComponent({
89
122
  // methods
90
123
  clickTab,
91
124
  keydown,
92
- density,
125
+ handleDragStart,
126
+ handleDragEnd,
93
127
  };
94
128
  },
95
129
  });
@@ -3,9 +3,11 @@
3
3
  :id="instance.name"
4
4
  ref="root"
5
5
  v-show="instance.isVisible"
6
- :class="['zd-tabs-tab', instance.cssClass]"
6
+ :class="['zd-tabs-tab', instance.cssClass, {
7
+ 'zd-tabs-tab-sortable': sortable,
8
+ }]"
7
9
  :style="$styleObject(instance.cssStyle)"
8
- :name="instance.tabName"
10
+ :name="instance.tabTitle"
9
11
  :disabled="instance.disabled"
10
12
  :theme="instance.theme"
11
13
  :color="instance.color"
@@ -15,11 +17,14 @@
15
17
  :iconName="instance.iconName"
16
18
  :rounded="instance.rounded"
17
19
  :selected-class="'v-tab--selected '+instance.selectedClass"
18
- :value="instance.value"
20
+ :value="instance.name || instance.value"
19
21
  :variant="instance.variant"
20
22
  :width="instance.width"
23
+ :draggable="sortable"
21
24
  @click="clickTab($event)"
22
25
  @keydown="keydown($event)"
26
+ @dragstart="handleDragStart"
27
+ @dragend="handleDragEnd"
23
28
  >
24
29
  <span class="zd-tabs-tab-text">
25
30
  {{ $t(instance.tabTitle) }}
@@ -46,6 +51,14 @@
46
51
  line-height: 15px;
47
52
  margin-bottom: 1px;
48
53
  }
54
+
55
+ &-sortable::before {
56
+ content: "⋮";
57
+ position: absolute;
58
+ left: 1px;
59
+ width: 10px;
60
+ cursor: grab;
61
+ }
49
62
  }
50
63
  }
51
64
  </style>
@@ -4,8 +4,8 @@ import { ZdComponentRenderProps } from '../zd-component/ZdComponentRender';
4
4
 
5
5
  export const ZdTabItemProps = buildProps({
6
6
  ...ZdComponentRenderProps,
7
- index: {
8
- type: [Number],
7
+ value: {
8
+ type: [String],
9
9
  },
10
10
  lazyLoad: {
11
11
  type: [Boolean],
@@ -2,7 +2,9 @@
2
2
  <v-tabs-window-item
3
3
  class="zd-tabs-tab-item"
4
4
  v-show="isVisible"
5
- :value="index"
5
+ :value="value"
6
+ :transition="false"
7
+ :reverse-transition="false"
6
8
  >
7
9
  <v-container fluid>
8
10
  <slot>
@@ -1,5 +1,5 @@
1
1
  import { Tabs } from '@zeedhi/common';
2
- import { defineComponent } from 'vue';
2
+ import { computed, defineComponent, ref } from 'vue';
3
3
  import { useDensity } from '../../composables';
4
4
  import { HeightProps } from '../../propsMixins/heightProps';
5
5
  import { buildProps } from '../../utils';
@@ -45,6 +45,10 @@ export const ZdTabsProps = buildProps({
45
45
  max: {
46
46
  type: [Number, String],
47
47
  },
48
+ sortable: {
49
+ type: [Boolean, String],
50
+ default: false,
51
+ },
48
52
  });
49
53
 
50
54
  /**
@@ -56,9 +60,13 @@ const tabsComponent = defineComponent({
56
60
  setup(props, ctx) {
57
61
  const { instance, root } = useCreateInstance<Tabs>(props, ctx, Tabs, ZdTabsProps);
58
62
  const { density } = useDensity({ instance });
63
+ const rootElement = getRootElement(root);
59
64
 
60
65
  const { click, focus, blur, mouseenter, mouseleave } = useGetMethods(instance, root);
61
66
 
67
+ const isDragOver = ref<boolean>(false);
68
+ const dragOverIndex = ref<number>(-1);
69
+
62
70
  const change = () => {
63
71
  const rootElement = getRootElement(root);
64
72
  instance.change(new Event('change'), rootElement.value);
@@ -73,10 +81,93 @@ const tabsComponent = defineComponent({
73
81
  const rootElement = getRootElement(root);
74
82
  instance.beforeChange(event, index, rootElement.value);
75
83
  };
84
+
85
+ const isTabOK = (event: DragEvent): boolean => {
86
+ return !!event.dataTransfer?.types.includes(`application/x-zd-tabs-owner-${instance.name.toLowerCase()}`);
87
+ };
88
+
89
+ const getTabsBarRect = (): DOMRect | undefined => {
90
+ return rootElement.value?.querySelector('.v-tabs')?.getBoundingClientRect();
91
+ };
92
+
93
+ const handleDragOver = (event: DragEvent): void => {
94
+ event.preventDefault();
95
+
96
+ if (!isTabOK(event)) {
97
+ dragOverIndex.value = -1;
98
+ return;
99
+ }
100
+
101
+ const tabsRect = getTabsBarRect();
102
+ if (!tabsRect) return;
103
+
104
+ if (event.clientY < tabsRect.top - 10 || event.clientY > tabsRect.bottom + 10) {
105
+ dragOverIndex.value = -1;
106
+ return;
107
+ }
108
+
109
+ const tabs = rootElement.value!.querySelectorAll('.zd-tabs-tab');
110
+ let targetIndex = instance.tabs.length;
111
+
112
+ tabs.forEach((tabEl, index) => {
113
+ const rect = tabEl.getBoundingClientRect();
114
+
115
+ if (event.clientX < rect.left + rect.width / 2) {
116
+ targetIndex = Math.min(targetIndex, index);
117
+ }
118
+ });
119
+
120
+ dragOverIndex.value = targetIndex;
121
+ event.stopPropagation();
122
+ };
123
+
124
+ const handleDrop = (event: DragEvent): void => {
125
+ event.preventDefault();
126
+
127
+ if (!isTabOK(event) || dragOverIndex.value === -1) return;
128
+
129
+ event.stopPropagation();
130
+
131
+ const sourceIndex = Number(event.dataTransfer?.getData('application/x-zd-tab-index'));
132
+ instance.moveTab(sourceIndex, dragOverIndex.value);
133
+
134
+ isDragOver.value = false;
135
+ dragOverIndex.value = -1;
136
+ };
137
+
138
+ const handleDragEnter = (event: DragEvent): void => {
139
+ event.preventDefault();
140
+
141
+ if (!isTabOK(event)) {
142
+ isDragOver.value = false;
143
+ dragOverIndex.value = -1;
144
+ return;
145
+ }
146
+
147
+ isDragOver.value = true;
148
+ };
149
+
150
+ const handleDragLeave = (event: DragEvent): void => {
151
+ if (rootElement.value && event.relatedTarget && rootElement.value.contains(event.relatedTarget as Node)) return;
152
+
153
+ isDragOver.value = false;
154
+ dragOverIndex.value = -1;
155
+ };
156
+
157
+ const activeTabName = computed<string | undefined>({
158
+ get: () => instance.tabs[instance.activeTab]?.name,
159
+ set: (name) => {
160
+ const index = instance.tabs.findIndex((tab) => tab.name === name);
161
+ if (index !== -1) instance.activeTab = index;
162
+ },
163
+ });
76
164
 
77
165
  return {
78
166
  instance,
79
167
  root,
168
+ dragOverIndex,
169
+ density,
170
+ activeTabName,
80
171
  click,
81
172
  focus,
82
173
  blur,
@@ -85,7 +176,10 @@ const tabsComponent = defineComponent({
85
176
  clickTab,
86
177
  keydown,
87
178
  change,
88
- density,
179
+ handleDragOver,
180
+ handleDrop,
181
+ handleDragEnter,
182
+ handleDragLeave,
89
183
  };
90
184
  },
91
185
  });
@@ -10,9 +10,13 @@
10
10
  maxHeight: instance.maxHeight,
11
11
  minHeight:instance.minHeight,
12
12
  }"
13
+ @dragenter="handleDragEnter"
14
+ @dragleave="handleDragLeave"
15
+ @dragover="handleDragOver"
16
+ @drop="handleDrop"
13
17
  >
14
18
  <v-tabs
15
- v-model="instance.activeTab"
19
+ v-model="activeTabName"
16
20
  show-arrows
17
21
  @update:model-value="change"
18
22
  :theme="instance.theme"
@@ -24,31 +28,39 @@
24
28
  :grow="instance.grow"
25
29
  :max="instance.max"
26
30
  >
27
- <zd-tab
28
- v-for="(tab, index) in instance.tabs " :key="tab.name"
29
- v-bind="{
30
- ...tab,
31
- name: tab.name,
32
- tabName: tab.name,
33
- dense: tab.dense || instance.dense,
34
- }"
35
- @click="clickTab($event, index)"
36
- @keydown="keydown($event, index)"
37
- >
38
- </zd-tab>
31
+ <template v-for="(tab, index) in instance.tabs " :key="tab.name">
32
+ <span
33
+ v-if="dragOverIndex === index"
34
+ class="zd-tabs-sortable-drop-indicator"
35
+ />
36
+
37
+ <zd-tab
38
+ v-bind="{
39
+ ...tab,
40
+ name: tab.name,
41
+ dense: tab.dense || instance.dense,
42
+ }"
43
+ @click="clickTab($event, index)"
44
+ @keydown="keydown($event, index)"
45
+ />
46
+ </template>
47
+
48
+ <span
49
+ v-if="dragOverIndex === instance.tabs.length"
50
+ class="zd-tabs-sortable-drop-indicator"
51
+ />
39
52
  </v-tabs>
40
53
 
41
54
  <v-window
42
- v-model="instance.activeTab"
55
+ :model-value="activeTabName"
43
56
  >
44
57
  <zd-tab-item
45
58
  v-for="(tab, index) in instance.tabs"
46
- v-show="tab.isVisible && index === instance.activeTab"
59
+ v-show="tab.isVisible && tab.name === activeTabName"
47
60
  :key="tab.name"
48
- :value="index"
61
+ :value="tab.name"
49
62
  :children ="tab.children"
50
63
  v-bind ="{
51
- index: index,
52
64
  name: instance.name+'-tab-item-'+index,
53
65
  lazyLoad: tab.lazyLoad,
54
66
  }"
@@ -113,5 +125,22 @@
113
125
  height:100% !important;
114
126
  }
115
127
  }
128
+
129
+ &-sortable-drop-indicator {
130
+ display: inline-block;
131
+ position: relative;
132
+ height: 100%;
133
+ width: 0;
134
+ z-index: 1;
135
+
136
+ &::after {
137
+ content: '';
138
+ width: 3px;
139
+ background-color: var(--v-primary-base);
140
+ height: 100%;
141
+ position: absolute;
142
+ opacity: 0.75;
143
+ }
144
+ }
116
145
  }
117
146
  </style>
@@ -171,6 +171,11 @@ export function useTextInput<TG extends TextInput>(
171
171
  });
172
172
  };
173
173
 
174
+ const clearInput = () => {
175
+ inputScope.input();
176
+ inputScope.change();
177
+ };
178
+
174
179
  const getIconClickEvents = () => {
175
180
  const events: any = {};
176
181
  if (instance.events.appendIconClick) {
@@ -207,6 +212,7 @@ export function useTextInput<TG extends TextInput>(
207
212
  appendOuterIconClick,
208
213
  prependOuterIconClick,
209
214
  setBlur,
215
+ clearInput,
210
216
  getIconClickEvents,
211
217
  };
212
218
  }
@@ -47,7 +47,7 @@
47
47
  @change="change()"
48
48
  @keyup="keyup($event)"
49
49
  @keydown="keydown($event)"
50
- @click:clear="change()"
50
+ @click:clear="clearInput()"
51
51
  :hide-details="instance.autoHintDetails ? 'auto' : false"
52
52
  :tabindex="instance.tabStop ? '' : '-1'"
53
53
  v-bind="{