@veritree/ui 0.27.0 → 0.28.0-1

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 (116) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/index.js +105 -75
  3. package/mixins/floating-ui-content.js +17 -4
  4. package/mixins/floating-ui-item.js +31 -15
  5. package/mixins/floating-ui.js +142 -24
  6. package/mixins/form-control-icon.js +3 -3
  7. package/mixins/form-control.js +45 -20
  8. package/nuxt.js +38 -26
  9. package/package.json +17 -6
  10. package/src/components/Alert/VTAlert.vue +55 -14
  11. package/src/components/Avatar/VTAvatarImage.vue +6 -26
  12. package/src/components/Badge/VTBadge.vue +60 -0
  13. package/src/components/Badge/VTBadgeNew.vue +60 -0
  14. package/src/components/Breadcrumb/VTBreadcrumbItem.vue +11 -0
  15. package/src/components/Breadcrumb/VTBreadcrumbLink.vue +40 -0
  16. package/src/components/Breadcrumb/VTBreadcrumbList.vue +11 -0
  17. package/src/components/Breadcrumb/VTBreadcrumbRoot.vue +11 -0
  18. package/src/components/Breadcrumb/VTBreadcrumbSeparator.vue +19 -0
  19. package/src/components/Button/VTButton.vue +104 -56
  20. package/src/components/Carousel/VTCarousel.vue +69 -0
  21. package/src/components/Carousel/VTCarouselBackward.vue +36 -0
  22. package/src/components/Carousel/VTCarouselForward.vue +38 -0
  23. package/src/components/Carousel/VTCarouselTracker.vue +80 -0
  24. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  25. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  26. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  27. package/src/components/Chip/VTChip.vue +29 -0
  28. package/src/components/Dialog/VTDialog.vue +59 -25
  29. package/src/components/Dialog/VTDialogClose.vue +3 -2
  30. package/src/components/Dialog/VTDialogContent.vue +29 -7
  31. package/src/components/Dialog/VTDialogFooter.vue +17 -2
  32. package/src/components/Dialog/VTDialogHeader.vue +2 -1
  33. package/src/components/Dialog/VTDialogMain.vue +5 -1
  34. package/src/components/Dialog/VTDialogOverlay.vue +5 -1
  35. package/src/components/Dialog/VTDialogTitle.vue +1 -1
  36. package/src/components/Disclosure/VTDisclosure.vue +2 -11
  37. package/src/components/Disclosure/VTDisclosureContent.vue +26 -52
  38. package/src/components/Disclosure/VTDisclosureDetails.vue +27 -2
  39. package/src/components/Disclosure/VTDisclosureHeader.vue +56 -89
  40. package/src/components/Disclosure/VTDisclosureIcon.vue +42 -31
  41. package/src/components/Divider/VTDivider.vue +9 -0
  42. package/src/components/Drawer/VTDrawer.vue +6 -15
  43. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  44. package/src/components/Drawer/VTDrawerContent.vue +10 -10
  45. package/src/components/Drawer/VTDrawerFooter.vue +4 -4
  46. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  47. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  48. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  49. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  50. package/src/components/DropdownMenu/VTDropdownMenu.vue +0 -6
  51. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +10 -1
  52. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  53. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +5 -1
  54. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  55. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
  56. package/src/components/Form/VTFieldset.vue +5 -0
  57. package/src/components/Form/VTForm.vue +11 -0
  58. package/src/components/Form/VTFormCol.vue +20 -0
  59. package/src/components/Form/VTFormFeedback.vue +7 -1
  60. package/src/components/Form/VTFormGroup.vue +5 -7
  61. package/src/components/Form/VTFormLabel.vue +22 -0
  62. package/src/components/Form/VTFormLabelHelper.vue +22 -0
  63. package/src/components/Form/VTFormRow.vue +5 -0
  64. package/src/components/Form/VTInput.vue +2 -5
  65. package/src/components/Form/VTInputDate.vue +602 -0
  66. package/src/components/Form/VTInputIcon.vue +3 -9
  67. package/src/components/Form/VTInputNumber.vue +198 -0
  68. package/src/components/Form/VTInputPassword.vue +14 -5
  69. package/src/components/Form/VTInputRange.vue +92 -0
  70. package/src/components/Form/VTLegend.vue +24 -0
  71. package/src/components/Form/VTTextarea.vue +2 -2
  72. package/src/components/Image/VTImage.vue +10 -10
  73. package/src/components/Listbox/VTListbox.vue +128 -9
  74. package/src/components/Listbox/VTListboxContent.vue +14 -1
  75. package/src/components/Listbox/VTListboxDivider.vue +21 -0
  76. package/src/components/Listbox/VTListboxGroup.vue +9 -0
  77. package/src/components/Listbox/VTListboxItem.vue +57 -15
  78. package/src/components/Listbox/VTListboxLabel.vue +5 -4
  79. package/src/components/Listbox/VTListboxList.vue +1 -6
  80. package/src/components/Listbox/VTListboxPlaceholder.vue +25 -0
  81. package/src/components/Listbox/VTListboxSearch.vue +12 -8
  82. package/src/components/Listbox/VTListboxTrigger.vue +87 -6
  83. package/src/components/Listbox/VTListboxTriggerHighlight.vue +204 -0
  84. package/src/components/Listbox/VTListboxViewport.vue +33 -0
  85. package/src/components/Popover/VTPopoverContent.vue +3 -3
  86. package/src/components/Popover/VTPopoverDivider.vue +1 -1
  87. package/src/components/Popover/VTPopoverItem.vue +6 -2
  88. package/src/components/ProgressBar/VTProgressBar.vue +35 -10
  89. package/src/components/ProgressBar/VTProgressBarIndicator.vue +53 -0
  90. package/src/components/ScrollShadows/VTScrollShadows.vue +76 -0
  91. package/src/components/Separator/VTSeparator.vue +13 -0
  92. package/src/components/Switch/VTSwitch.vue +61 -0
  93. package/src/components/Tabs/VTTab.vue +6 -5
  94. package/src/components/Tabs/VTTabGroup.vue +88 -9
  95. package/src/components/Tabs/VTTabPanel.vue +4 -5
  96. package/src/components/Toast/README.md +263 -0
  97. package/src/components/Toast/VTToast.vue +145 -0
  98. package/src/components/Toast/VTToastAction.vue +25 -0
  99. package/src/components/Toast/VTToastClose.vue +52 -0
  100. package/src/components/Toast/VTToastContent.vue +25 -0
  101. package/src/components/Toast/VTToastDescription.vue +36 -0
  102. package/src/components/Toast/VTToastIcon.vue +72 -0
  103. package/src/components/Toast/VTToastItem.vue +180 -0
  104. package/src/components/Toast/VTToastTitle.vue +34 -0
  105. package/src/components/Tooltip/VTTooltipTrigger.vue +3 -5
  106. package/src/components/Transitions/FadeInOut.vue +2 -2
  107. package/src/components/Utils/FloatingUi.vue +31 -13
  108. package/src/helpers/currency.js +21 -0
  109. package/src/utils/components.js +18 -0
  110. package/src/utils/images.js +31 -12
  111. package/src/components/Input/VTInput.vue +0 -82
  112. package/src/components/Input/VTInputDate.vue +0 -36
  113. package/src/components/Input/VTInputFile.vue +0 -60
  114. package/src/components/Input/VTInputUpload.vue +0 -54
  115. package/src/components/Modal/VTModal.vue +0 -69
  116. package/src/utils/genId.js +0 -13
@@ -1,8 +1,9 @@
1
1
  <template>
2
2
  <li
3
3
  :id="id"
4
- :class="classComputed"
4
+ :class="computedClasses"
5
5
  :aria-disabled="disabled"
6
+ :disabled="disabled"
6
7
  :aria-selected="String(selected)"
7
8
  :tabindex="tabIndex"
8
9
  :role="'option'"
@@ -16,10 +17,25 @@
16
17
  @keydown.enter.prevent="onClick"
17
18
  @keydown.tab.prevent
18
19
  >
19
- <slot></slot>
20
- <span v-if="wasSelected" class="ml-auto">
21
- <IconCheckOutline class="text-secondary-200 h-5 w-5" />
22
- </span>
20
+ <template v-if="this.multiple">
21
+ <input
22
+ :id="`${id}-checkbox`"
23
+ :ref="`${id}-checkbox`"
24
+ :value="value"
25
+ :checked="checked"
26
+ class="form-control-check"
27
+ type="checkbox"
28
+ @click.stop
29
+ @change="onChange(value, $event)"
30
+ />
31
+ <slot></slot>
32
+ </template>
33
+ <template v-else>
34
+ <slot></slot>
35
+ <span v-if="checked" class="ml-auto">
36
+ <IconCheckOutline class="text-secondary-300 h-5 w-5" />
37
+ </span>
38
+ </template>
23
39
  </li>
24
40
  </template>
25
41
 
@@ -54,6 +70,10 @@ export default {
54
70
  },
55
71
 
56
72
  computed: {
73
+ computedClasses() {
74
+ return this.classComputed;
75
+ },
76
+
57
77
  componentContent() {
58
78
  return this.apiInjected().componentContent;
59
79
  },
@@ -66,22 +86,30 @@ export default {
66
86
  return this.apiListbox().search;
67
87
  },
68
88
 
69
- /**
70
- * The difference between selected (in the mixin) and
71
- * wasSelected is that selected is more related to
72
- * the aria-selected while wasSelected is the
73
- * real selected option for the listbox
74
- */
75
- wasSelected() {
89
+ multiple() {
90
+ return this.apiListbox().multiple;
91
+ },
92
+
93
+ checked() {
94
+ if (this.multiple) {
95
+ return this.apiListbox().valueComputed.some(
96
+ (value) => JSON.stringify(this.value) === JSON.stringify(value),
97
+ );
98
+ }
99
+
76
100
  return (
77
101
  JSON.stringify(this.value) ===
78
- JSON.stringify(this.apiListbox().selectedValue)
102
+ JSON.stringify(this.apiListbox().valueComputed)
79
103
  );
80
104
  },
81
105
  },
82
106
 
83
107
  mounted() {
84
- if (this.wasSelected) {
108
+ if (this.multiple) {
109
+ return;
110
+ }
111
+
112
+ if (this.checked) {
85
113
  /**
86
114
  * There are some conflicts between the portal and the interaction
87
115
  * with the element. It's unclear why it happens but if no delay,
@@ -141,7 +169,7 @@ export default {
141
169
  * with any of the items to get its index value
142
170
  */
143
171
  const newItemSelectedIndex = this.items.findIndex((item) =>
144
- item.text.toLowerCase().includes(this.search.toLowerCase())
172
+ item.text.toLowerCase().includes(this.search.toLowerCase()),
145
173
  );
146
174
 
147
175
  /**
@@ -160,6 +188,20 @@ export default {
160
188
  this.apiListbox().clearSearch();
161
189
  }, 1000);
162
190
  },
191
+
192
+ /**
193
+ * On change is used only when multiple is set to true.
194
+ * It handles the checkbox changes to interact with
195
+ * the provider by pushing or removing values.
196
+ *
197
+ * @param {*} value
198
+ * @param {Object} event
199
+ */
200
+ onChange(value, event) {
201
+ event.target.checked
202
+ ? this.apiListbox().pushValueToValueComputed(value)
203
+ : this.apiListbox().removeValueFromValueComputed(value);
204
+ },
163
205
  },
164
206
  };
165
207
  </script>
@@ -1,10 +1,11 @@
1
1
  <template>
2
2
  <component
3
3
  :is="as"
4
- :class="{
5
- ListboxLabel: headless,
6
- 'mb-2 block text-xs font-normal uppercase': !headless,
7
- }"
4
+ :class="[
5
+ headless
6
+ ? 'listbox-label'
7
+ : 'mb-0.5 block px-3 text-xs font-normal uppercase text-gray-600',
8
+ ]"
8
9
  >
9
10
  <slot></slot>
10
11
  </component>
@@ -1,10 +1,5 @@
1
1
  <template>
2
- <ul
3
- :id="id"
4
- :class="[
5
- headless ? 'listbox-list' : '-mx-3 max-h-[160px] w-auto overflow-y-auto',
6
- ]"
7
- >
2
+ <ul :id="id" :class="[headless ? 'listbox-list' : null]">
8
3
  <slot></slot>
9
4
  </ul>
10
5
  </template>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <component
3
+ :is="as"
4
+ :class="[headless ? 'listbox-placeholder' : 'font-light text-gray-500']"
5
+ >
6
+ <slot></slot>
7
+ </component>
8
+ </template>
9
+
10
+ <script>
11
+ export default {
12
+ name: 'VTListboxPlaceholder',
13
+
14
+ props: {
15
+ as: {
16
+ type: String,
17
+ default: 'span',
18
+ },
19
+ headless: {
20
+ type: Boolean,
21
+ default: false,
22
+ },
23
+ },
24
+ };
25
+ </script>
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <div class="-mx-3 -mt-2">
3
3
  <input
4
- ref="search"
4
+ ref="searchInput"
5
5
  v-model="search"
6
6
  v-bind="$attrs"
7
7
  type="text"
8
- class="leading-0 font-inherit w-full max-w-full appearance-none border-b border-solid border-gray-300 py-2 px-3 text-base text-inherit"
8
+ class="leading-0 hidden sm:block font-inherit w-full max-w-full appearance-none border-b border-solid border-gray-300 py-2 px-3 text-base text-inherit"
9
9
  @input="onChange"
10
10
  @click.stop
11
11
  @keydown.down.prevent="focusNextItem"
@@ -29,6 +29,8 @@ export default {
29
29
 
30
30
  inheritAttrs: false,
31
31
 
32
+ emits: ['change'],
33
+
32
34
  inject: ['apiListbox'],
33
35
 
34
36
  data() {
@@ -59,12 +61,11 @@ export default {
59
61
  };
60
62
 
61
63
  this.apiListbox().registerSearch(componentSearch);
62
- this.$nextTick(() => setTimeout(() => this.$refs.search.focus(), 150));
64
+ this.$nextTick(() => setTimeout(() => this.$refs.searchInput.focus(), 150));
63
65
  },
64
66
 
65
- beforeDestroy() {
67
+ beforeUnmount() {
66
68
  this.search = '';
67
- this.$emit('change', this.search.trim());
68
69
  },
69
70
 
70
71
  methods: {
@@ -111,6 +112,7 @@ export default {
111
112
 
112
113
  // select new item
113
114
  if (this.items[newSelectedIndex]) {
115
+ this.index = newSelectedIndex;
114
116
  this.items[newSelectedIndex].select();
115
117
  }
116
118
  },
@@ -124,10 +126,12 @@ export default {
124
126
  },
125
127
 
126
128
  onChange() {
127
- this.index = 0;
128
- if (this.item) this.item.select();
129
-
130
129
  this.$emit('change', this.search.trim());
130
+
131
+ this.$nextTick(() => {
132
+ this.index = 0;
133
+ if (this.item) this.item.select();
134
+ });
131
135
  },
132
136
 
133
137
  onKeyEnter() {
@@ -1,10 +1,12 @@
1
1
  <template>
2
2
  <button
3
3
  :id="id"
4
- :class="classComputed"
5
- :disabled="disabled"
4
+ :data-testid="dataTestidComputed"
5
+ :class="classList"
6
+ :disabled="isDisabled"
6
7
  :aria-expanded="expanded"
7
8
  :aria-haspopup="hasPopup"
9
+ :role="role"
8
10
  type="button"
9
11
  @click.prevent="onClick"
10
12
  @keydown.down.prevent="onKeyDownOrUp"
@@ -14,9 +16,19 @@
14
16
  <span :class="[headless ? 'listbox-button__text' : 'truncate text-left']">
15
17
  <slot></slot>
16
18
  </span>
17
- <span :class="[headless ? 'listbox-button__icon' : 'shrink-0']">
19
+ <span
20
+ :class="[
21
+ headless ? 'listbox-button__icon' : '-mr-1 ml-2 shrink-0 text-gray-500',
22
+ ]"
23
+ >
24
+ <VTSpinner v-if="loading" class="mr-0.5 max-w-4 max-h-4" />
25
+ <IconChevronDownV2
26
+ v-else-if="apiListbox().version === '2'"
27
+ :class="{ 'rotate-180': expanded }"
28
+ />
18
29
  <IconChevronDown
19
- class="transition-transform"
30
+ v-else
31
+ class="w-5 text-gray-700 transition-transform"
20
32
  :class="{ 'rotate-180': expanded }"
21
33
  />
22
34
  </span>
@@ -39,6 +51,27 @@ export default {
39
51
 
40
52
  inject: ['apiListbox'],
41
53
 
54
+ inheritAttrs: false,
55
+
56
+ props: {
57
+ dataTestid: {
58
+ type: String,
59
+ default: null,
60
+ },
61
+ role: {
62
+ type: String,
63
+ default: 'combobox',
64
+ },
65
+ loading: {
66
+ type: Boolean,
67
+ default: false,
68
+ },
69
+ stopPropagation: {
70
+ type: Boolean,
71
+ default: false,
72
+ },
73
+ },
74
+
42
75
  data() {
43
76
  return {
44
77
  expanded: false,
@@ -51,10 +84,18 @@ export default {
51
84
  return `listbox-trigger-${this.apiListbox().id}`;
52
85
  },
53
86
 
87
+ dataTestidComputed() {
88
+ return this.dataTestid || `listbox-trigger-${this.apiListbox().id}`;
89
+ },
90
+
54
91
  componentContent() {
55
92
  return this.apiListbox().componentContent;
56
93
  },
57
94
 
95
+ multiple() {
96
+ return this.apiListbox().multiple;
97
+ },
98
+
58
99
  items() {
59
100
  return this.apiListbox().items;
60
101
  },
@@ -66,6 +107,42 @@ export default {
66
107
  lastMenuItem() {
67
108
  return this.items[this.items.length - 1];
68
109
  },
110
+
111
+ classList() {
112
+ if (this.headless) {
113
+ return this.$attrs.class || null;
114
+ }
115
+
116
+ // TODO: role isn't the best way to determine button styles, we should have a better prop for that
117
+ if (this.role === 'combobox') {
118
+ const version2Classes = [];
119
+
120
+ if (this.apiListbox().version === '2') {
121
+ version2Classes.push('listbox-trigger--version-2');
122
+
123
+ if (this.variant) {
124
+ version2Classes.push(`listbox-trigger--${this.variant}`);
125
+ }
126
+
127
+ if (this.size) {
128
+ version2Classes.push(`listbox-trigger--${this.size}`);
129
+ }
130
+ }
131
+
132
+ return [
133
+ this.classComputed,
134
+ this.headless ? null : 'hover:bg-gray-200',
135
+ ...version2Classes,
136
+ this.$attrs.class,
137
+ ];
138
+ }
139
+
140
+ return `button-base button--${this.variant} button--${this.size}`;
141
+ },
142
+
143
+ isDisabled() {
144
+ return this.disabled || this.loading;
145
+ },
69
146
  },
70
147
 
71
148
  mounted() {
@@ -122,7 +199,11 @@ export default {
122
199
  },
123
200
 
124
201
  onClick(e) {
202
+ if (this.stopPropagation) {
203
+ e.stopPropagation();
204
+ }
125
205
  this.init(e);
206
+ this.$emit('click');
126
207
  },
127
208
 
128
209
  onKeyDownOrUp(e) {
@@ -135,8 +216,8 @@ export default {
135
216
  keyCode === 'ArrowDown'
136
217
  ? 'firstMenuItem'
137
218
  : keyCode === 'ArrowUp'
138
- ? 'lastMenuItem'
139
- : null;
219
+ ? 'lastMenuItem'
220
+ : null;
140
221
 
141
222
  // settimeout here is delaying the focusing the element
142
223
  // since it is not rendered yet. All items will only
@@ -0,0 +1,204 @@
1
+ <template>
2
+ <div
3
+ :id="highlightId"
4
+ :class="[
5
+ headless ? 'listbox-highlight' : 'relative',
6
+ headless
7
+ ? isActive
8
+ ? 'listbox-highlight--active'
9
+ : null
10
+ : isActive
11
+ ? '[&>*]:border-gray-700'
12
+ : null,
13
+ ]"
14
+ >
15
+ <slot />
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import { computePosition, offset, autoUpdate } from '@floating-ui/dom';
21
+
22
+ export default {
23
+ name: 'VTListboxHighlight',
24
+
25
+ inject: ['apiListbox'],
26
+
27
+ props: {
28
+ /**
29
+ * Determines whether the button will use its default atomic style (tailwind) or its default class
30
+ * @type {boolean}
31
+ * @values
32
+ * - true: The button will have no default style and can be fully customized with a custom class
33
+ * - false: The button will use its default atomic style (tailwind) and can be further customized with additional classes
34
+ * @default null
35
+ */
36
+ headless: {
37
+ type: Boolean,
38
+ default: false,
39
+ },
40
+ /**
41
+ * The default value for the listbox item, used to determine its initial state.
42
+ * @type {string|null}
43
+ * @default null
44
+ */
45
+ defaultValue: {
46
+ type: String,
47
+ default: null,
48
+ },
49
+ },
50
+
51
+ computed: {
52
+ /**
53
+ * Computed property that generates an identifier for the counter element associated with the listbox.
54
+ *
55
+ * @property
56
+ * @name counterId
57
+ * @memberof VTListboxTriggerHighlight
58
+ * @description Returns an ID for the listbox counter element.
59
+ * @returns {string} The generated counter ID.
60
+ */
61
+ counterId() {
62
+ return `listbox-counter-${this.apiListbox().id}`;
63
+ },
64
+
65
+ /**
66
+ * Computed property that generates an identifier for the highlight element associated with the listbox.
67
+ *
68
+ * @property
69
+ * @name highlightId
70
+ * @memberof VTListboxTriggerHighlight
71
+ * @description Returns an ID for the listbox highlight element.
72
+ * @returns {string} The generated highlight ID.
73
+ */
74
+ highlightId() {
75
+ return `listbox-highlight-${this.apiListbox().id}`;
76
+ },
77
+
78
+ /**
79
+ * Computes the current value of the listbox item.
80
+ *
81
+ * @property
82
+ * @name computedValue
83
+ * @memberof VTListboxTriggerHighlight
84
+ * @description Returns the computed value of the listbox item.
85
+ * @returns {*} The computed value.
86
+ */
87
+ computedValue() {
88
+ return this.apiListbox().valueComputed;
89
+ },
90
+
91
+ /**
92
+ * Checks if the computed value is an array.
93
+ *
94
+ * @property
95
+ * @name isValueAnArray
96
+ * @memberof VTListboxTriggerHighlight
97
+ * @description Checks if the computed value is an array.
98
+ * @returns {boolean} True if the value is an array, false otherwise.
99
+ */
100
+ isValueAnArray() {
101
+ return Array.isArray(this.computedValue);
102
+ },
103
+
104
+ /**
105
+ * Computes the length of the value, considering whether it's an array or a single value.
106
+ *
107
+ * @property
108
+ * @name computedValueLength
109
+ * @memberof VTListboxTriggerHighlight
110
+ * @description Returns the length of the computed value.
111
+ * @returns {number} The length of the computed value.
112
+ */
113
+ computedValueLength() {
114
+ if (this.isValueAnArray) {
115
+ return this.computedValue.length;
116
+ } else {
117
+ return this.computedValue ? 1 : 0;
118
+ }
119
+ },
120
+
121
+ /**
122
+ * Determines if the listbox item is active based on its value and default value.
123
+ *
124
+ * @property
125
+ * @name isActive
126
+ * @memberof VTListboxTriggerHighlight
127
+ * @description Checks if the listbox item is considered active.
128
+ * @returns {boolean} True if the listbox item is active, false otherwise.
129
+ */
130
+ isActive() {
131
+ return this.isValueAnArray
132
+ ? this.computedValueLength > 0
133
+ : this.defaultValue !== this.computedValue;
134
+ },
135
+
136
+ // /**
137
+ // * Checks if the badge should be visible for the listbox item.
138
+ // *
139
+ // * @property
140
+ // * @name isBadgeVisible
141
+ // * @memberof VTListboxTriggerHighlight
142
+ // * @description Checks if the badge should be visible for the listbox item.
143
+ // * @returns {boolean} True if the badge should be visible, false otherwise.
144
+ // */
145
+ // isBadgeVisible() {
146
+ // return this.isValueAnArray && this.isActive;
147
+ // },
148
+ },
149
+
150
+ // mounted() {
151
+ // this.$nextTick(() => this.positionFloatingContent());
152
+ // },
153
+
154
+ // methods: {
155
+ // /**
156
+ // * Positions the floating content relative to a specified trigger element.
157
+ // *
158
+ // * @function
159
+ // * @name positionFloatingContent
160
+ // * @description Calculates and updates the position of the floating content
161
+ // * based on the position of the reference element.
162
+ // * @returns {void}
163
+ // */
164
+ // positionFloatingContent() {
165
+ // /**
166
+ // * The reference element that triggers the positioning of the floating content.
167
+ // * @type {HTMLElement}
168
+ // */
169
+ // const referenceElement = document.getElementById(this.highlightId);
170
+
171
+ // /**
172
+ // * The floating element whose position needs to be updated.
173
+ // * @type {HTMLElement}
174
+ // */
175
+ // const floatingElement = document.getElementById(this.counterId);
176
+
177
+ // /**
178
+ // * Callback function to update the position of the floating element
179
+ // * using the autoUpdate and computePosition utilities.
180
+ // * @type {Function}
181
+ // */
182
+ // const updatePositionCallback = () => {
183
+ // computePosition(referenceElement, floatingElement, {
184
+ // placement: 'top-end',
185
+ // middleware: [
186
+ // offset({
187
+ // alignmentAxis: -10,
188
+ // mainAxis: -10,
189
+ // }),
190
+ // ],
191
+ // }).then(({ x, y }) => {
192
+ // Object.assign(floatingElement.style, {
193
+ // left: `${x}px`,
194
+ // top: `${y}px`,
195
+ // });
196
+ // });
197
+ // };
198
+
199
+ // // Call the autoUpdate function with the specified elements and callback.
200
+ // autoUpdate(referenceElement, floatingElement, updatePositionCallback);
201
+ // },
202
+ // },
203
+ };
204
+ </script>
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <div
3
+ :id="id"
4
+ :class="[
5
+ headless
6
+ ? 'listbox-viewport'
7
+ : '-mx-3 max-h-[300px] w-auto overflow-y-auto scroll-auto',
8
+ ]"
9
+ >
10
+ <slot></slot>
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+ export default {
16
+ name: 'VTListboxViewport',
17
+
18
+ inject: ['apiListbox'],
19
+
20
+ props: {
21
+ headless: {
22
+ type: Boolean,
23
+ default: false,
24
+ },
25
+ },
26
+
27
+ computed: {
28
+ id() {
29
+ return `listbox-viewport-${this.apiListbox().id}`;
30
+ },
31
+ },
32
+ };
33
+ </script>
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <FloatingUi
3
- :id="id"
4
3
  :visible="visible"
4
+ :id="id"
5
5
  :headless="headless"
6
- :portal-class="$vnode.data.staticClass"
7
- component="popover"
6
+ :class="{ 'popover-content': headless }"
7
+ :floating-ui-class="floatingUiClass"
8
8
  >
9
9
  <slot></slot>
10
10
  </FloatingUi>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  :class="{
4
- 'popover-divider': headless,
4
+ PopoverDivider: headless,
5
5
  'h-[1px]': !headless,
6
6
  }"
7
7
  ></div>
@@ -5,7 +5,7 @@
5
5
  // default styles
6
6
  headless
7
7
  ? 'popover-item'
8
- : 'relative z-10 -mx-3 flex items-center gap-2 px-3 py-2 text-inherit no-underline hover:bg-secondary-200/10',
8
+ : 'hover:bg-secondary-200/10 relative z-10 -mx-3 flex items-center gap-2 px-3 py-2 text-inherit no-underline',
9
9
  ]"
10
10
  @click="onClick"
11
11
  >
@@ -44,7 +44,11 @@ export default {
44
44
  },
45
45
 
46
46
  as() {
47
- return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
47
+ return this.href
48
+ ? 'a'
49
+ : this.to
50
+ ? resolveComponent('NuxtLink')
51
+ : 'button';
48
52
  },
49
53
  },
50
54