@v1nt1248/3nclient-lib 0.3.28 → 0.3.29

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 (111) hide show
  1. package/dist/chunks/ui3n-notification-Dr_3Td9N.js +279 -0
  2. package/dist/components/index.d.ts +12 -12
  3. package/dist/components/ui3n-autocomplete/types.d.ts +8 -0
  4. package/dist/components/ui3n-autocomplete/ui3n-autocomplete.d.ts +2 -2
  5. package/dist/components/ui3n-badge/types.d.ts +12 -0
  6. package/dist/components/ui3n-badge/ui3n-badge-simple.d.ts +1 -1
  7. package/dist/components/ui3n-badge/ui3n-badge.d.ts +1 -1
  8. package/dist/components/ui3n-breadcrumbs/types.d.ts +1 -1
  9. package/dist/components/ui3n-breadcrumbs/ui3n-breadcrumb.d.ts +2 -2
  10. package/dist/components/ui3n-button/types.d.ts +4 -2
  11. package/dist/components/ui3n-checkbox/types.d.ts +11 -0
  12. package/dist/components/ui3n-checkbox/ui3n-checkbox.d.ts +4 -1
  13. package/dist/components/ui3n-chip/types.d.ts +6 -1
  14. package/dist/components/ui3n-chip/ui3n-chip.d.ts +2 -0
  15. package/dist/components/ui3n-drop-files/types.d.ts +7 -0
  16. package/dist/components/ui3n-drop-files/ui3n-drop-files.d.ts +7 -1
  17. package/dist/components/ui3n-editable/types.d.ts +11 -0
  18. package/dist/components/ui3n-editable/ui3n-editable.d.ts +4 -2
  19. package/dist/components/ui3n-icon/types.d.ts +5 -1
  20. package/dist/components/ui3n-icon/ui3n-icon.d.ts +2 -2
  21. package/dist/components/ui3n-input/types.d.ts +4 -0
  22. package/dist/components/ui3n-input/ui3n-input.d.ts +4 -1
  23. package/dist/components/ui3n-input-file/types.d.ts +11 -0
  24. package/dist/components/ui3n-input-file/ui3n-input-file.d.ts +4 -1
  25. package/dist/components/ui3n-list/types.d.ts +4 -0
  26. package/dist/components/ui3n-menu/types.d.ts +4 -0
  27. package/dist/components/ui3n-menu/ui3n-menu.d.ts +1 -1
  28. package/dist/components/ui3n-notification/ui3n-notification.d.ts +2 -2
  29. package/dist/components/ui3n-progress/ui3n-progress-circular.d.ts +1 -1
  30. package/dist/components/ui3n-progress/ui3n-progress-linear.d.ts +1 -1
  31. package/dist/components/ui3n-radio-group/types.d.ts +18 -0
  32. package/dist/components/ui3n-radio-group/ui3n-radio-group.d.ts +3 -1
  33. package/dist/components/ui3n-radio-group/ui3n-radio.d.ts +6 -7
  34. package/dist/components/ui3n-scrollbar-vertical/types.d.ts +2 -0
  35. package/dist/components/ui3n-scrollbar-vertical/ui3n-scrollbar-vertical.d.ts +2 -0
  36. package/dist/components/ui3n-selector/types.d.ts +11 -0
  37. package/dist/components/ui3n-selector/ui3n-selector.d.ts +2 -2
  38. package/dist/components/ui3n-slider/types.d.ts +11 -0
  39. package/dist/components/ui3n-slider/ui3n-slider.d.ts +4 -1
  40. package/dist/components/ui3n-step-line-bar/types.d.ts +4 -0
  41. package/dist/components/ui3n-switch/types.d.ts +11 -0
  42. package/dist/components/ui3n-switch/ui3n-switch.d.ts +4 -1
  43. package/dist/components/ui3n-table/composables/useTable.d.ts +1 -0
  44. package/dist/components/ui3n-table/types.d.ts +4 -0
  45. package/dist/components/ui3n-table/ui3n-table-sort-icon.d.ts +4 -1
  46. package/dist/components/ui3n-tabs/types.d.ts +4 -0
  47. package/dist/components/ui3n-text/types.d.ts +11 -0
  48. package/dist/components/ui3n-text/ui3n-text.d.ts +4 -1
  49. package/dist/components/ui3n-tooltip/types.d.ts +4 -0
  50. package/dist/components/ui3n-tooltip/ui3n-tooltip.d.ts +4 -2
  51. package/dist/style.css +1 -1
  52. package/dist/ui3n-components.js +2066 -1690
  53. package/dist/ui3n-plugins.js +1 -1
  54. package/package.json +1 -1
  55. package/src/components/index.ts +29 -7
  56. package/src/components/ui3n-autocomplete/types.ts +9 -1
  57. package/src/components/ui3n-autocomplete/ui3n-autocomplete.vue +182 -51
  58. package/src/components/ui3n-badge/types.ts +10 -0
  59. package/src/components/ui3n-badge/ui3n-badge-simple.vue +54 -55
  60. package/src/components/ui3n-badge/ui3n-badge.vue +4 -0
  61. package/src/components/ui3n-breadcrumbs/types.ts +1 -1
  62. package/src/components/ui3n-breadcrumbs/ui3n-breadcrumb.vue +7 -5
  63. package/src/components/ui3n-button/types.ts +4 -2
  64. package/src/components/ui3n-button/ui3n-button.vue +24 -19
  65. package/src/components/ui3n-checkbox/types.ts +12 -0
  66. package/src/components/ui3n-checkbox/ui3n-checkbox.vue +79 -29
  67. package/src/components/ui3n-chip/types.ts +6 -1
  68. package/src/components/ui3n-chip/ui3n-chip.vue +64 -61
  69. package/src/components/ui3n-dialog/ui3n-dialog.vue +3 -3
  70. package/src/components/ui3n-drop-files/types.ts +8 -0
  71. package/src/components/ui3n-drop-files/ui3n-drop-files.vue +73 -29
  72. package/src/components/ui3n-editable/types.ts +12 -0
  73. package/src/components/ui3n-editable/ui3n-editable.vue +56 -24
  74. package/src/components/ui3n-icon/types.ts +5 -1
  75. package/src/components/ui3n-icon/ui3n-icon.vue +45 -50
  76. package/src/components/ui3n-input/types.ts +4 -0
  77. package/src/components/ui3n-input/ui3n-input.vue +14 -1
  78. package/src/components/ui3n-input-file/types.ts +12 -0
  79. package/src/components/ui3n-input-file/ui3n-input-file.vue +33 -16
  80. package/src/components/ui3n-list/types.ts +4 -0
  81. package/src/components/ui3n-list/ui3n-list.vue +3 -1
  82. package/src/components/ui3n-menu/types.ts +4 -0
  83. package/src/components/ui3n-menu/ui3n-menu.vue +43 -32
  84. package/src/components/ui3n-notification/ui3n-notification.vue +190 -175
  85. package/src/components/ui3n-progress/ui3n-progress-circular.vue +40 -22
  86. package/src/components/ui3n-progress/ui3n-progress-linear.vue +14 -7
  87. package/src/components/ui3n-radio-group/types.ts +20 -0
  88. package/src/components/ui3n-radio-group/ui3n-radio-group.vue +61 -48
  89. package/src/components/ui3n-radio-group/ui3n-radio.vue +60 -65
  90. package/src/components/ui3n-scrollbar-vertical/types.ts +2 -0
  91. package/src/components/ui3n-scrollbar-vertical/ui3n-scrollbar-vertical.vue +4 -4
  92. package/src/components/ui3n-selector/types.ts +12 -0
  93. package/src/components/ui3n-selector/ui3n-selector.vue +63 -40
  94. package/src/components/ui3n-slider/types.ts +12 -0
  95. package/src/components/ui3n-slider/ui3n-slider.vue +88 -39
  96. package/src/components/ui3n-step-line-bar/types.ts +4 -0
  97. package/src/components/ui3n-step-line-bar/ui3n-step-line-bar.vue +8 -10
  98. package/src/components/ui3n-switch/types.ts +12 -0
  99. package/src/components/ui3n-switch/ui3n-switch.vue +57 -25
  100. package/src/components/ui3n-table/composables/useTable.ts +17 -0
  101. package/src/components/ui3n-table/types.ts +4 -0
  102. package/src/components/ui3n-table/ui3n-table-sort-icon.vue +9 -8
  103. package/src/components/ui3n-table/ui3n-table.vue +48 -17
  104. package/src/components/ui3n-tabs/types.ts +4 -0
  105. package/src/components/ui3n-tabs/ui3n-tabs.vue +146 -108
  106. package/src/components/ui3n-text/types.ts +12 -0
  107. package/src/components/ui3n-text/ui3n-text.vue +56 -15
  108. package/src/components/ui3n-tooltip/types.ts +4 -0
  109. package/src/components/ui3n-tooltip/ui3n-tooltip.vue +61 -43
  110. package/src/components/ui3n-virtual-scroll/ui3n-virtual-scroll.vue +201 -17
  111. package/dist/chunks/ui3n-notification-DlDM-u-R.js +0 -276
@@ -1,5 +1,5 @@
1
1
  import { B as e, n as t, r as n, t as r } from "./chunks/plugins-keys-jqAZ5D94.js";
2
- import { t as i } from "./chunks/ui3n-notification-DlDM-u-R.js";
2
+ import { t as i } from "./chunks/ui3n-notification-Dr_3Td9N.js";
3
3
  import { createApp as a, markRaw as o, ref as s } from "vue";
4
4
  import "pinia";
5
5
  import c from "mitt";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@v1nt1248/3nclient-lib",
3
3
  "license": "AGPL-3.0-or-later",
4
4
  "author": "v1nt1248",
5
- "version": "0.3.28",
5
+ "version": "0.3.29",
6
6
  "description": "Library for 3NWeb clients",
7
7
  "type": "module",
8
8
  "files": [
@@ -6,20 +6,26 @@ import type { Ui3nButtonProps, Ui3nButtonEmits } from './ui3n-button/types';
6
6
  import Ui3nChip from './ui3n-chip/ui3n-chip.vue';
7
7
  import type { Ui3nChipProps, Ui3nChipEmits, Ui3nChipSlots } from './ui3n-chip/types';
8
8
  import Ui3nDropFiles from './ui3n-drop-files/ui3n-drop-files.vue';
9
- import type { Ui3nDropFilesProps, Ui3nDropFilesEmits, Ui3nDropFilesSlots } from './ui3n-drop-files/types';
9
+ import type {
10
+ Ui3nDropFilesProps,
11
+ Ui3nDropFilesEmits,
12
+ Ui3nDropFilesSlots,
13
+ Ui3nDropFilesExpose,
14
+ } from './ui3n-drop-files/types';
10
15
  import Ui3nEmoji from './ui3n-emoji/ui3n-emoji.vue';
11
16
  import type { Ui3nEmojiProps, Ui3nEmojiEmits } from './ui3n-emoji/types';
12
17
  import Ui3nInput from './ui3n-input/ui3n-input.vue';
13
18
  import type { Ui3nInputProps, Ui3nInputEmits, Ui3nInputSlots, Ui3nInputExpose } from './ui3n-input/types';
14
19
  import Ui3nInputFile from './ui3n-input-file/ui3n-input-file.vue';
15
- import type { Ui3nInputFileProps, Ui3nInputFileEmits } from './ui3n-input-file/types';
20
+ import type { Ui3nInputFileProps, Ui3nInputFileEmits, Ui3nInputFileExpose } from './ui3n-input-file/types';
16
21
  import Ui3nText from './ui3n-text/ui3n-text.vue';
17
- import type { Ui3nTextProps, Ui3nTextEmits } from './ui3n-text/types';
22
+ import type { Ui3nTextProps, Ui3nTextEmits, Ui3nTextExpose } from './ui3n-text/types';
18
23
  import Ui3nCheckbox from './ui3n-checkbox/ui3n-checkbox.vue';
19
24
  import type {
20
25
  Ui3nCheckboxProps,
21
26
  Ui3nCheckboxEmits,
22
27
  Ui3nCheckboxSlots,
28
+ Ui3nCheckboxExpose,
23
29
  Ui3nCheckboxValue,
24
30
  } from './ui3n-checkbox/types';
25
31
  import Ui3nNotification from './ui3n-notification/ui3n-notification.vue';
@@ -51,7 +57,7 @@ import type {
51
57
  Ui3nDialogEvent,
52
58
  } from './ui3n-dialog/types';
53
59
  import Ui3nMenu from './ui3n-menu/ui3n-menu.vue';
54
- import type { Ui3nMenuProps, Ui3nMenuEmits, Ui3nMenuSlots } from './ui3n-menu/types';
60
+ import type { Ui3nMenuProps, Ui3nMenuEmits, Ui3nMenuSlots, Ui3nMenuExpose } from './ui3n-menu/types';
55
61
  import Ui3nList from './ui3n-list/ui3n-list.vue';
56
62
  import type { Ui3nListProps, Ui3nListEmits, Ui3nListSlots } from './ui3n-list/types';
57
63
  import Ui3nVirtualScroll from './ui3n-virtual-scroll/ui3n-virtual-scroll.vue';
@@ -69,7 +75,7 @@ import type {
69
75
  Ui3nBreadcrumbsProps,
70
76
  } from './ui3n-breadcrumbs/types';
71
77
  import Ui3nSwitch from './ui3n-switch/ui3n-switch.vue';
72
- import type { Ui3nSwitchProps, Ui3nSwitchEmits, Ui3nSwitchSlots } from './ui3n-switch/types';
78
+ import type { Ui3nSwitchProps, Ui3nSwitchEmits, Ui3nSwitchSlots, Ui3nSwitchExpose } from './ui3n-switch/types';
73
79
  import Ui3nStepLineBar from './ui3n-step-line-bar/ui3n-step-line-bar.vue';
74
80
  import type { Ui3nStepLineBarProps } from './ui3n-step-line-bar/types';
75
81
  import Ui3nProgressLinear from './ui3n-progress/ui3n-progress-linear.vue';
@@ -88,28 +94,32 @@ import type {
88
94
  Ui3nRadioEmits,
89
95
  Ui3nRadioProps,
90
96
  Ui3nRadioSlots,
97
+ Ui3nRadioExpose,
91
98
  Ui3nRadioGroupEmits,
92
99
  Ui3nRadioGroupProps,
93
100
  Ui3nRadioGroupSlots,
101
+ Ui3nRadioGroupExpose,
94
102
  Ui3nRadioValue,
95
103
  } from './ui3n-radio-group/types';
96
104
  import Ui3nEditable from './ui3n-editable/ui3n-editable.vue';
97
- import type { Ui3nEditableProps, Ui3nEditableEmits } from './ui3n-editable/types';
105
+ import type { Ui3nEditableProps, Ui3nEditableEmits, Ui3nEditableExpose } from './ui3n-editable/types';
98
106
  import Ui3nAutocomplete from './ui3n-autocomplete/ui3n-autocomplete.vue';
99
107
  import type {
100
108
  Ui3nAutocompleteProps,
101
109
  Ui3nAutocompleteEmits,
102
110
  Ui3nAutocompleteSlots,
111
+ Ui3nAutocompleteExpose,
103
112
  Ui3nAutocompleteOptionBase,
104
113
  } from './ui3n-autocomplete/types';
105
114
  import Ui3nSlider from './ui3n-slider/ui3n-slider.vue';
106
- import type { UI3nSliderProps, UI3nSliderEmits } from './ui3n-slider/types';
115
+ import type { UI3nSliderProps, UI3nSliderEmits, UI3nSliderExpose } from './ui3n-slider/types';
107
116
  import Ui3nSelector from './ui3n-selector/ui3n-selector.vue';
108
117
  import type {
109
118
  Ui3nSelectorOptionBase,
110
119
  Ui3nSelectorProps,
111
120
  Ui3nSelectorEmits,
112
121
  Ui3nSelectorSlots,
122
+ Ui3nSelectorExpose,
113
123
  Ui3nSelectorItemDisplayingFunction,
114
124
  } from './ui3n-selector/types';
115
125
  import Ui3nMobileMenu from './ui3n-mobile-menu/ui3n-mobile-menu.vue';
@@ -150,6 +160,7 @@ export {
150
160
  Ui3nDropFilesProps,
151
161
  Ui3nDropFilesEmits,
152
162
  Ui3nDropFilesSlots,
163
+ Ui3nDropFilesExpose,
153
164
  Ui3nEmoji,
154
165
  Ui3nEmojiProps,
155
166
  Ui3nEmojiEmits,
@@ -161,13 +172,16 @@ export {
161
172
  Ui3nInputFile,
162
173
  Ui3nInputFileProps,
163
174
  Ui3nInputFileEmits,
175
+ Ui3nInputFileExpose,
164
176
  Ui3nText,
165
177
  Ui3nTextProps,
166
178
  Ui3nTextEmits,
179
+ Ui3nTextExpose,
167
180
  Ui3nCheckbox,
168
181
  Ui3nCheckboxProps,
169
182
  Ui3nCheckboxEmits,
170
183
  Ui3nCheckboxSlots,
184
+ Ui3nCheckboxExpose,
171
185
  Ui3nCheckboxValue,
172
186
  Ui3nNotification,
173
187
  Ui3nTableSortIcon,
@@ -197,6 +211,7 @@ export {
197
211
  Ui3nMenuProps,
198
212
  Ui3nMenuEmits,
199
213
  Ui3nMenuSlots,
214
+ Ui3nMenuExpose,
200
215
  Ui3nList,
201
216
  Ui3nListProps,
202
217
  Ui3nListEmits,
@@ -220,6 +235,7 @@ export {
220
235
  Ui3nSwitchProps,
221
236
  Ui3nSwitchEmits,
222
237
  Ui3nSwitchSlots,
238
+ Ui3nSwitchExpose,
223
239
  Ui3nStepLineBar,
224
240
  Ui3nStepLineBarProps,
225
241
  Ui3nProgressLinear,
@@ -237,24 +253,30 @@ export {
237
253
  Ui3nRadioEmits,
238
254
  Ui3nRadioProps,
239
255
  Ui3nRadioSlots,
256
+ Ui3nRadioExpose,
240
257
  Ui3nRadioGroupEmits,
241
258
  Ui3nRadioGroupProps,
242
259
  Ui3nRadioGroupSlots,
260
+ Ui3nRadioGroupExpose,
243
261
  Ui3nEditable,
244
262
  Ui3nEditableProps,
245
263
  Ui3nEditableEmits,
264
+ Ui3nEditableExpose,
246
265
  Ui3nAutocomplete,
247
266
  Ui3nAutocompleteProps,
248
267
  Ui3nAutocompleteEmits,
249
268
  Ui3nAutocompleteSlots,
269
+ Ui3nAutocompleteExpose,
250
270
  Ui3nAutocompleteOptionBase,
251
271
  Ui3nSlider,
252
272
  UI3nSliderProps,
253
273
  UI3nSliderEmits,
274
+ UI3nSliderExpose,
254
275
  Ui3nSelector,
255
276
  Ui3nSelectorProps,
256
277
  Ui3nSelectorEmits,
257
278
  Ui3nSelectorSlots,
279
+ Ui3nSelectorExpose,
258
280
  Ui3nSelectorOptionBase,
259
281
  Ui3nSelectorItemDisplayingFunction,
260
282
  Ui3nMobileMenu,
@@ -25,6 +25,10 @@ export type Ui3nAutocompleteValue<T extends Ui3nAutocompleteOptionBase> = {
25
25
  * Autocomplete component properties
26
26
  */
27
27
  export interface Ui3nAutocompleteProps<T extends Ui3nAutocompleteOptionBase> {
28
+ /**
29
+ * HTML name attribute for form submission
30
+ */
31
+ name?: string;
28
32
  /**
29
33
  * Whether to show chips
30
34
  * @default false
@@ -131,7 +135,7 @@ export interface Ui3nAutocompleteSlots<T extends Ui3nAutocompleteOptionBase> {
131
135
  /**
132
136
  * Chip slot
133
137
  */
134
- chip: (props: { item: T | T[keyof T]; index: number }) => VNode;
138
+ chip: (props: { item: T | T[keyof T]; index: number; isHighlighted: boolean }) => VNode;
135
139
  /**
136
140
  * No data text slot
137
141
  */
@@ -141,3 +145,7 @@ export interface Ui3nAutocompleteSlots<T extends Ui3nAutocompleteOptionBase> {
141
145
  */
142
146
  selection: (props: { value: T[] | Array<T[keyof T]> }) => VNode;
143
147
  }
148
+
149
+ export interface Ui3nAutocompleteExpose {
150
+ clear: () => void;
151
+ }
@@ -1,19 +1,3 @@
1
- <!--
2
- Copyright (C) 2025 3NSoft Inc.
3
-
4
- This program is free software: you can redistribute it and/or modify it under
5
- the terms of the GNU General Public License as published by the Free Software
6
- Foundation, either version 3 of the License, or (at your option) any later
7
- version.
8
-
9
- This program is distributed in the hope that it will be useful, but
10
- WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
- See the GNU General Public License for more details.
13
-
14
- You should have received a copy of the GNU General Public License along with
15
- this program. If not, see <http://www.gnu.org/licenses/>.
16
- -->
17
1
  <script setup lang="ts" generic="T extends Ui3nAutocompleteOptionBase">
18
2
  import { computed, ref, watch } from 'vue';
19
3
  import cloneDeep from 'lodash/cloneDeep';
@@ -21,14 +5,15 @@
21
5
  import size from 'lodash/size';
22
6
  import Ui3nChip from '../ui3n-chip/ui3n-chip.vue';
23
7
  import Ui3nMenu from '../ui3n-menu/ui3n-menu.vue';
24
- import Ui3nHtml from '@/directives/ui3n-html';
25
- import { markSearch, getRandomId } from '@/utils';
8
+ import Ui3nHtml from '../../directives/ui3n-html';
9
+ import { markSearch, getRandomId } from '../../utils';
26
10
  import type { Nullable } from '@/types';
27
- import {
11
+ import type {
28
12
  Ui3nAutocompleteOptionBase,
29
13
  Ui3nAutocompleteProps,
30
14
  Ui3nAutocompleteEmits,
31
15
  Ui3nAutocompleteSlots,
16
+ Ui3nAutocompleteExpose,
32
17
  } from './types';
33
18
 
34
19
  const vUi3nHtml = Ui3nHtml;
@@ -52,6 +37,7 @@
52
37
  const inputEl = ref<Nullable<HTMLInputElement>>(null);
53
38
  const menuBodyEl = ref<Nullable<HTMLDivElement>>(null);
54
39
  const activeItemsIndex = ref<Nullable<number>>(null);
40
+ const isLastChipHighlighted = ref(false);
55
41
  const isNewValueValid = ref(true);
56
42
 
57
43
  const ids = computed(() =>
@@ -93,12 +79,14 @@
93
79
  });
94
80
 
95
81
  function onInput() {
82
+ isLastChipHighlighted.value = false;
96
83
  emits('update:search', query.value);
97
84
  }
98
85
 
99
86
  function onBlur() {
100
87
  emits('update:focused', false);
101
88
  activeItemsIndex.value = null;
89
+ isLastChipHighlighted.value = false;
102
90
 
103
91
  setTimeout(() => {
104
92
  isMenuOpen.value = false;
@@ -206,30 +194,80 @@
206
194
  }
207
195
  }
208
196
 
209
- function onKeydown(event: KeyboardEvent, key: 'down' | 'up' | 'esc' | 'enter' | 'tab') {
197
+ function handleBackspaceKey() {
198
+ if (props.disabled || query.value !== '' || isEmpty(props.modelValue)) {
199
+ return;
200
+ }
201
+
202
+ if (!isLastChipHighlighted.value) {
203
+ isLastChipHighlighted.value = true;
204
+ return;
205
+ }
206
+
207
+ const updatedModelValue = cloneDeep(props.modelValue);
208
+ updatedModelValue.pop();
209
+ emits('update:modelValue', updatedModelValue);
210
+
211
+ isLastChipHighlighted.value = false;
212
+ }
213
+
214
+ function onKeydown(event: KeyboardEvent, key: 'down' | 'up' | 'esc' | 'enter' | 'tab' | 'backspace') {
210
215
  switch (key) {
211
- case 'down':
216
+ case 'down': {
212
217
  event.preventDefault();
213
218
  event.stopPropagation();
214
219
  handlePressingDownKey();
215
220
  break;
216
- case 'up':
221
+ }
222
+
223
+ case 'up': {
217
224
  event.preventDefault();
218
225
  event.stopPropagation();
219
226
  handlePressingUpKey();
220
227
  break;
228
+ }
229
+
221
230
  case 'esc':
222
231
  case 'tab':
223
232
  handlePressingEscOrTabKeys();
224
233
  break;
225
- case 'enter':
234
+
235
+ case 'enter': {
226
236
  event.preventDefault();
227
237
  event.stopPropagation();
228
238
  handlePressingEnterKey();
229
239
  break;
240
+ }
241
+
242
+ case 'backspace':
243
+ handleBackspaceKey();
244
+ break;
230
245
  }
231
246
  }
232
247
 
248
+ function clear() {
249
+ query.value = '';
250
+ isMenuOpen.value = false;
251
+ activeItemsIndex.value = null;
252
+ isNewValueValid.value = true;
253
+
254
+ emits('update:modelValue', [] as unknown as T[] & Array<T[keyof T]>);
255
+ emits('update:search', '');
256
+ }
257
+
258
+ defineExpose<Ui3nAutocompleteExpose>({
259
+ clear,
260
+ });
261
+
262
+ watch(
263
+ () => props.name,
264
+ newName => {
265
+ if (!newName) {
266
+ clear();
267
+ }
268
+ },
269
+ );
270
+
233
271
  watch(
234
272
  () => size(filteredItems.value),
235
273
  (val, oVal) => {
@@ -246,6 +284,42 @@
246
284
 
247
285
  <template>
248
286
  <div :class="$style.ui3nAutocomplete">
287
+ <!-- 'hidden inputs' block for setting of 'name' attr when used in a form -->
288
+ <fieldset
289
+ v-if="name && !isEmpty(modelValue)"
290
+ :class="$style.hiddenBlock"
291
+ >
292
+ <template v-if="!multiple">
293
+ <input
294
+ type="hidden"
295
+ :name="name"
296
+ :value="returnObject ? JSON.stringify(modelValue) : modelValue"
297
+ />
298
+ </template>
299
+
300
+ <template v-else>
301
+ <template v-if="!returnObject">
302
+ <input
303
+ v-for="(val, index) in modelValue as Array<T[keyof T]>"
304
+ :key="`${name}-flat-${index}`"
305
+ type="hidden"
306
+ :name="`${name}[]`"
307
+ :value="val"
308
+ />
309
+ </template>
310
+
311
+ <template v-else>
312
+ <input
313
+ v-for="(item, index) in modelValue as T[]"
314
+ :key="item.id || `${name}-obj-${index}`"
315
+ type="hidden"
316
+ :name="`${name}[]`"
317
+ :value="JSON.stringify(item)"
318
+ />
319
+ </template>
320
+ </template>
321
+ </fieldset>
322
+
249
323
  <ui3n-menu
250
324
  v-model="isMenuOpen"
251
325
  :offset-x="2"
@@ -258,19 +332,31 @@
258
332
  ref="activatorEl"
259
333
  :class="$style.trigger"
260
334
  >
261
- <template v-if="chips">
335
+ <transition-group
336
+ v-if="chips"
337
+ name="chipAnim"
338
+ tag="div"
339
+ :class="$style.chipsContainer"
340
+ >
262
341
  <!-- @vue-ignore -->
263
- <template
342
+ <div
264
343
  v-for="(item, index) in modelValue"
265
- :key="item.id"
344
+ :key="item.id || index"
345
+ :class="$style.chipWrapper"
266
346
  >
267
347
  <slot
268
348
  name="chip"
269
349
  :item="item"
270
350
  :index="index"
351
+ :is-highlighted="index === size(modelValue) - 1 && isLastChipHighlighted"
271
352
  >
272
353
  <ui3n-chip
273
354
  height="32"
355
+ :color="
356
+ index === size(modelValue) - 1 && isLastChipHighlighted
357
+ ? 'var(--color-bg-control-primary-hover)'
358
+ : undefined
359
+ "
274
360
  round
275
361
  closeable
276
362
  @close="onChipClose(item)"
@@ -278,8 +364,8 @@
278
364
  {{ returnObject ? (item as T)[props.itemTitle] : item }}
279
365
  </ui3n-chip>
280
366
  </slot>
281
- </template>
282
- </template>
367
+ </div>
368
+ </transition-group>
283
369
 
284
370
  <template v-else>
285
371
  <div :class="$style.displayValue">
@@ -302,6 +388,7 @@
302
388
  @keydown.esc="onKeydown($event, 'esc')"
303
389
  @keydown.enter="onKeydown($event, 'enter')"
304
390
  @keydown.tab="onKeydown($event, 'tab')"
391
+ @keydown.delete="onKeydown($event, 'backspace')"
305
392
  />
306
393
  </div>
307
394
 
@@ -356,11 +443,16 @@
356
443
 
357
444
  <style lang="scss" module>
358
445
  .ui3nAutocomplete {
359
- --autocomplete-min-height: var(--spacing-l);
446
+ --ui3n-autocomplete-min-height: 32px;
447
+ --ui3n-autocomplete-font-size: 12px;
448
+ --ui3n-autocomplete-item-font-size: 13px;
449
+ --ui3n-autocomplete-padding-inline: 8px;
450
+ --ui3n-autocomplete-padding-block: 4px;
451
+ --ui3n-autocomplete-border-radius: 4px;
360
452
 
361
453
  position: relative;
362
454
  width: 100%;
363
- min-height: var(--autocomplete-min-height);
455
+ min-height: var(--ui3n-autocomplete-min-height);
364
456
 
365
457
  :global(.match-search) {
366
458
  font-weight: 600;
@@ -368,29 +460,36 @@
368
460
  }
369
461
  }
370
462
 
463
+ .hiddenBlock {
464
+ display: none;
465
+ border: none;
466
+ padding: 0;
467
+ margin: 0;
468
+ }
469
+
371
470
  .trigger {
372
471
  display: flex;
373
472
  width: 100%;
374
473
  flex-wrap: wrap;
375
474
  justify-content: flex-start;
376
475
  align-items: flex-start;
377
- gap: var(--spacing-xs);
476
+ gap: 4px;
378
477
  }
379
478
 
380
479
  .displayValue {
381
- font-size: var(--font-12);
382
- line-height: var(--autocomplete-min-height);
480
+ font-size: var(--ui3n-autocomplete-font-size);
481
+ line-height: var(--ui3n-autocomplete-min-height);
383
482
  font-weight: 400;
384
483
  color: var(--color-text-control-primary-default);
385
484
  }
386
485
 
387
486
  .input {
388
- border-radius: var(--spacing-xs);
389
- padding: 0 var(--spacing-s);
487
+ border-radius: var(--ui3n-autocomplete-border-radius);
488
+ padding: 0 var(--ui3n-autocomplete-padding-inline);
390
489
  flex-grow: 1;
391
- height: var(--autocomplete-min-height);
392
- font-size: var(--font-12);
393
- line-height: var(--autocomplete-min-height);
490
+ height: var(--ui3n-autocomplete-min-height);
491
+ font-size: var(--ui3n-autocomplete-font-size);
492
+ line-height: var(--ui3n-autocomplete-min-height);
394
493
  font-weight: 400;
395
494
  color: var(--color-text-control-primary-default);
396
495
  background-color: transparent;
@@ -407,8 +506,8 @@
407
506
  }
408
507
 
409
508
  &.inputWithError {
410
- height: calc(var(--autocomplete-min-height) - 2px);
411
- padding: 0 calc(var(--spacing-s) - 1px);
509
+ height: calc(var(--ui3n-autocomplete-min-height) - 2px);
510
+ padding: 0 calc(var(--ui3n-autocomplete-padding-inline) - 1px);
412
511
  border: 1px solid var(--error-content-default);
413
512
  }
414
513
  }
@@ -416,20 +515,20 @@
416
515
  .body {
417
516
  position: relative;
418
517
  background-color: var(--color-bg-block-primary-default);
419
- padding: var(--spacing-xs);
518
+ padding: 4px;
420
519
  }
421
520
 
422
521
  .item {
423
522
  display: flex;
424
- min-height: var(--spacing-l);
523
+ min-height: var(--ui3n-autocomplete-min-height);
425
524
  justify-content: flex-start;
426
525
  align-items: center;
427
- padding: var(--spacing-xs) var(--spacing-s);
428
- font-size: var(--font-13);
429
- line-height: var(--font-16);
526
+ padding: var(--ui3n-autocomplete-padding-block) var(--ui3n-autocomplete-padding-inline);
527
+ font-size: var(--ui3n-autocomplete-item-font-size);
528
+ line-height: 1.23;
430
529
  font-weight: 500;
431
530
  color: var(--color-text-control-primary-default);
432
- border-radius: var(--spacing-xs);
531
+ border-radius: var(--ui3n-autocomplete-border-radius);
433
532
  user-select: none;
434
533
  cursor: pointer;
435
534
 
@@ -452,14 +551,46 @@
452
551
 
453
552
  .noData {
454
553
  display: flex;
455
- min-height: var(--spacing-l);
554
+ min-height: var(--ui3n-autocomplete-min-height);
456
555
  justify-content: flex-start;
457
556
  align-items: center;
458
- padding: var(--spacing-xs) var(--spacing-s);
459
- font-size: var(--font-13);
460
- line-height: var(--font-16);
557
+ padding: var(--ui3n-autocomplete-padding-block) var(--ui3n-autocomplete-padding-inline);
558
+ font-size: var(--ui3n-autocomplete-item-font-size);
559
+ line-height: 1.23;
461
560
  font-weight: 500;
462
561
  color: var(--color-text-control-primary-default);
463
- border-radius: var(--spacing-xs);
562
+ border-radius: var(--ui3n-autocomplete-border-radius);
563
+ }
564
+
565
+ .chipsContainer {
566
+ display: flex;
567
+ flex-wrap: wrap;
568
+ gap: 4px;
569
+ align-items: flex-start;
570
+ }
571
+
572
+ .chipWrapper {
573
+ display: inline-flex;
574
+ }
575
+
576
+ :global {
577
+ .chipAnim-enter-from,
578
+ .chipAnim-leave-to {
579
+ opacity: 0;
580
+ transform: scale(0.85);
581
+ }
582
+
583
+ .chipAnim-enter-active,
584
+ .chipAnim-leave-active {
585
+ transition: all 0.2s ease;
586
+ }
587
+
588
+ .chipAnim-move {
589
+ transition: transform 0.2s ease;
590
+ }
591
+
592
+ .chipAnim-leave-active {
593
+ position: absolute !important;
594
+ }
464
595
  }
465
596
  </style>
@@ -1,6 +1,10 @@
1
1
  import type { VNode } from 'vue';
2
2
 
3
3
  export interface Ui3nBadgeSimpleProps {
4
+ /**
5
+ * Root element id
6
+ */
7
+ id?: string;
4
8
  /** For simple display as a circle */
5
9
  dot?: boolean;
6
10
  /** Text displayed inside the circle */
@@ -11,7 +15,13 @@ export interface Ui3nBadgeSimpleProps {
11
15
  textColor?: string;
12
16
  }
13
17
 
18
+ export interface Ui3nBadgeSimpleEmits {
19
+ (event: 'change:size', val: { width: number; height: number }): void;
20
+ }
21
+
14
22
  export interface Ui3nBadgeProps {
23
+ /** Root element id*/
24
+ id?: string;
15
25
  /** For simple display as a circle */
16
26
  dot?: boolean;
17
27
  /** Text displayed inside the circle */