@veritree/ui 0.22.2 → 0.22.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 (75) hide show
  1. package/index.js +64 -72
  2. package/mixins/floating-ui-content.js +1 -22
  3. package/mixins/floating-ui-item.js +101 -51
  4. package/mixins/floating-ui.js +7 -9
  5. package/mixins/form-control-icon.js +5 -5
  6. package/mixins/form-control.js +17 -18
  7. package/nuxt.js +30 -23
  8. package/package.json +14 -6
  9. package/src/components/Alert/VTAlert.vue +55 -14
  10. package/src/components/Button/VTButton.vue +20 -12
  11. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  12. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  13. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  14. package/src/components/Dialog/VTDialog.vue +22 -32
  15. package/src/components/Dialog/VTDialogClose.vue +19 -25
  16. package/src/components/Dialog/VTDialogContent.vue +24 -19
  17. package/src/components/Dialog/VTDialogFooter.vue +11 -16
  18. package/src/components/Dialog/VTDialogHeader.vue +16 -18
  19. package/src/components/Dialog/VTDialogMain.vue +11 -18
  20. package/src/components/Dialog/VTDialogOverlay.vue +14 -18
  21. package/src/components/Dialog/VTDialogTitle.vue +10 -7
  22. package/src/components/Disclosure/VTDisclosureContent.vue +1 -1
  23. package/src/components/Disclosure/VTDisclosureDetails.vue +1 -1
  24. package/src/components/Disclosure/VTDisclosureHeader.vue +2 -2
  25. package/src/components/Disclosure/VTDisclosureIcon.vue +1 -1
  26. package/src/components/Drawer/VTDrawer.vue +6 -15
  27. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  28. package/src/components/Drawer/VTDrawerContent.vue +9 -9
  29. package/src/components/Drawer/VTDrawerFooter.vue +3 -3
  30. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  31. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  32. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  33. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  34. package/src/components/DropdownMenu/VTDropdownMenu.vue +19 -6
  35. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +14 -6
  36. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  37. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +7 -3
  38. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  39. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
  40. package/src/components/Form/VTFormFeedback.vue +11 -5
  41. package/src/components/Form/VTFormGroup.vue +5 -7
  42. package/src/components/Form/VTFormLabel.vue +22 -0
  43. package/src/components/Form/VTFormRow.vue +5 -0
  44. package/src/components/Form/VTInput.vue +7 -7
  45. package/src/components/Form/VTInputIcon.vue +1 -2
  46. package/src/components/Form/VTInputPassword.vue +14 -5
  47. package/src/components/Form/VTTextarea.vue +1 -1
  48. package/src/components/Image/VTImage.vue +33 -4
  49. package/src/components/Listbox/VTListbox.vue +105 -14
  50. package/src/components/Listbox/VTListboxContent.vue +3 -7
  51. package/src/components/Listbox/VTListboxItem.vue +127 -6
  52. package/src/components/Listbox/VTListboxLabel.vue +3 -4
  53. package/src/components/Listbox/VTListboxList.vue +3 -24
  54. package/src/components/Listbox/VTListboxSearch.vue +64 -55
  55. package/src/components/Listbox/VTListboxTrigger.vue +9 -4
  56. package/src/components/Popover/VTPopover.vue +19 -0
  57. package/src/components/Popover/VTPopoverItem.vue +6 -2
  58. package/src/components/ProgressBar/VTProgressBar.vue +21 -3
  59. package/src/components/Skeleton/VTSkeleton.vue +11 -0
  60. package/src/components/Skeleton/VTSkeletonItem.vue +9 -0
  61. package/src/components/Tabs/VTTab.vue +6 -5
  62. package/src/components/Tabs/VTTabGroup.vue +9 -7
  63. package/src/components/Tabs/VTTabPanel.vue +4 -5
  64. package/src/components/Tooltip/VTTooltip.vue +65 -0
  65. package/src/components/Tooltip/VTTooltipContent.vue +59 -0
  66. package/src/components/Tooltip/VTTooltipTrigger.vue +98 -0
  67. package/src/components/Transitions/FadeInOut.vue +2 -2
  68. package/src/components/Utils/FloatingUi.vue +56 -24
  69. package/src/utils/components.js +18 -0
  70. package/src/components/Input/VTInput.vue +0 -82
  71. package/src/components/Input/VTInputDate.vue +0 -36
  72. package/src/components/Input/VTInputFile.vue +0 -60
  73. package/src/components/Input/VTInputUpload.vue +0 -54
  74. package/src/components/Modal/VTModal.vue +0 -69
  75. package/src/utils/genId.js +0 -13
package/index.js CHANGED
@@ -1,69 +1,65 @@
1
- import VTAlert from "./src/components/Alert/VTAlert.vue";
2
- import VTAvatar from "./src/components/Avatar/VTAvatar.vue";
3
- import VTAvatarImage from "./src/components/Avatar/VTAvatarImage.vue";
4
- import VTAvatarText from "./src/components/Avatar/VTAvatarText.vue";
5
- import VTButton from "./src/components/Button/VTButton.vue";
6
- import VTImage from "./src/components/Image/VTImage.vue";
7
- import VTImageCounter from "./src/components/Image/VTImageCounter.vue";
8
- import VTImageHover from "./src/components/Image/VTImageHover.vue";
9
- import VTDropdownMenu from "./src/components/DropdownMenu/VTDropdownMenu.vue";
10
- import VTDropdownMenuContent from "./src/components/DropdownMenu/VTDropdownMenuContent.vue";
11
- import VTDropdownMenuDivider from "./src/components/DropdownMenu/VTDropdownMenuDivider.vue";
12
- import VTDropdownMenuGroup from "./src/components/DropdownMenu/VTDropdownMenuGroup.vue";
13
- import VTDropdownMenuItem from "./src/components/DropdownMenu/VTDropdownMenuItem.vue";
14
- import VTDropdownMenuLabel from "./src/components/DropdownMenu/VTDropdownMenuLabel.vue";
15
- import VTDropdownMenuTrigger from "./src/components/DropdownMenu/VTDropdownMenuTrigger.vue";
16
- import VTPopover from "./src/components/Popover/VTPopover.vue";
17
- import VTPopoverContent from "./src/components/Popover/VTPopoverContent.vue";
18
- import VTPopoverDivider from "./src/components/Popover/VTPopoverDivider.vue";
19
- import VTPopoverGroup from "./src/components/Popover/VTPopoverGroup.vue";
20
- import VTPopoverItem from "./src/components/Popover/VTPopoverItem.vue";
21
- import VTPopoverTrigger from "./src/components/Popover/VTPopoverTrigger.vue";
22
- import VTFormFeedback from "./src/components/Form/VTFormFeedback.vue";
23
- import VTFormGroup from "./src/components/Form/VTFormGroup.vue";
24
- import VTInput from "./src/components/Form/VTInput.vue";
25
- import VTInputIcon from "./src/components/Form/VTInputIcon.vue";
26
- import VTInputPassword from "./src/components/Form/VTInputPassword.vue";
27
- import VTListbox from "./src/components/Listbox/VTListbox.vue";
28
- import VTListboxContent from "./src/components/Listbox/VTListboxContent.vue";
29
- import VTListboxItem from "./src/components/Listbox/VTListboxItem.vue";
30
- import VTListboxLabel from "./src/components/Listbox/VTListboxLabel.vue";
31
- import VTListboxList from "./src/components/Listbox/VTListboxList.vue";
32
- import VTListboxSearch from "./src/components/Listbox/VTListboxSearch.vue";
33
- import VTListboxTrigger from "./src/components/Listbox/VTListboxTrigger.vue";
34
- import VTSpinner from "./src/components/Spinner/VTSpinner.vue";
35
- import VTInputDate from "./src/components/Input/VTInputDate.vue";
36
- import VTInputFile from "./src/components/Input/VTInputFile.vue";
37
- import VTInputUpload from "./src/components/Input/VTInputUpload.vue";
38
- import VTProgressBar from "./src/components/ProgressBar/VTProgressBar.vue";
39
- import VTTextarea from "./src/components/Textarea/VTTextarea.vue";
40
- import VTModal from "./src/components/Modal/VTModal.vue";
41
- import VTTab from "./src/components/Tabs/VTTab.vue";
42
- import VTTabGroup from "./src/components/Tabs/VTTabGroup.vue";
43
- import VTTabList from "./src/components/Tabs/VTTabList.vue";
44
- import VTTabPanel from "./src/components/Tabs/VTTabPanel.vue";
45
- import VTTabPanels from "./src/components/Tabs/VTTabPanels.vue";
46
- import VTDialog from "./src/components/Dialog/VTDialog.vue";
47
- import VTDialogClose from "./src/components/Dialog/VTDialogClose.vue";
48
- import VTDialogContent from "./src/components/Dialog/VTDialogContent.vue";
49
- import VTDialogFooter from "./src/components/Dialog/VTDialogFooter.vue";
50
- import VTDialogHeader from "./src/components/Dialog/VTDialogHeader.vue";
51
- import VTDialogMain from "./src/components/Dialog/VTDialogMain.vue";
52
- import VTDialogOverlay from "./src/components/Dialog/VTDialogOverlay.vue";
53
- import VTDialogTitle from "./src/components/Dialog/VTDialogTitle.vue";
54
- import VTDrawer from "./src/components/Drawer/VTDrawer.vue";
55
- import VTDrawerClose from "./src/components/Drawer/VTDrawerClose.vue";
56
- import VTDrawerContent from "./src/components/Drawer/VTDrawerContent.vue";
57
- import VTDrawerFooter from "./src/components/Drawer/VTDrawerFooter.vue";
58
- import VTDrawerHeader from "./src/components/Drawer/VTDrawerHeader.vue";
59
- import VTDrawerTitle from "./src/components/Drawer/VTDrawerTitle.vue";
60
- import VTDrawerMain from "./src/components/Drawer/VTDrawerMain.vue";
61
- import VTDrawerOverlay from "./src/components/Drawer/VTDrawerOverlay.vue";
62
- import VTDisclosure from "./src/components/Disclosure/VTDisclosure.vue";
63
- import VTDisclosureDetails from "./src/components/Disclosure/VTDisclosureDetails.vue";
64
- import VTDisclosureHeader from "./src/components/Disclosure/VTDisclosureHeader.vue";
65
- import VTDisclosureIcon from "./src/components/Disclosure/VTDisclosureIcon.vue";
66
- import VTDisclosureContent from "./src/components/Disclosure/VTDisclosureContent.vue";
1
+ import VTAlert from './src/components/Alert/VTAlert.vue';
2
+ import VTAvatar from './src/components/Avatar/VTAvatar.vue';
3
+ import VTAvatarImage from './src/components/Avatar/VTAvatarImage.vue';
4
+ import VTAvatarText from './src/components/Avatar/VTAvatarText.vue';
5
+ import VTButton from './src/components/Button/VTButton.vue';
6
+ import VTImage from './src/components/Image/VTImage.vue';
7
+ import VTImageCounter from './src/components/Image/VTImageCounter.vue';
8
+ import VTImageHover from './src/components/Image/VTImageHover.vue';
9
+ import VTDropdownMenu from './src/components/DropdownMenu/VTDropdownMenu.vue';
10
+ import VTDropdownMenuContent from './src/components/DropdownMenu/VTDropdownMenuContent.vue';
11
+ import VTDropdownMenuDivider from './src/components/DropdownMenu/VTDropdownMenuDivider.vue';
12
+ import VTDropdownMenuGroup from './src/components/DropdownMenu/VTDropdownMenuGroup.vue';
13
+ import VTDropdownMenuItem from './src/components/DropdownMenu/VTDropdownMenuItem.vue';
14
+ import VTDropdownMenuLabel from './src/components/DropdownMenu/VTDropdownMenuLabel.vue';
15
+ import VTDropdownMenuTrigger from './src/components/DropdownMenu/VTDropdownMenuTrigger.vue';
16
+ import VTPopover from './src/components/Popover/VTPopover.vue';
17
+ import VTPopoverContent from './src/components/Popover/VTPopoverContent.vue';
18
+ import VTPopoverDivider from './src/components/Popover/VTPopoverDivider.vue';
19
+ import VTPopoverGroup from './src/components/Popover/VTPopoverGroup.vue';
20
+ import VTPopoverItem from './src/components/Popover/VTPopoverItem.vue';
21
+ import VTPopoverTrigger from './src/components/Popover/VTPopoverTrigger.vue';
22
+ import VTFormFeedback from './src/components/Form/VTFormFeedback.vue';
23
+ import VTFormGroup from './src/components/Form/VTFormGroup.vue';
24
+ import VTListbox from './src/components/Listbox/VTListbox.vue';
25
+ import VTListboxContent from './src/components/Listbox/VTListboxContent.vue';
26
+ import VTListboxItem from './src/components/Listbox/VTListboxItem.vue';
27
+ import VTListboxLabel from './src/components/Listbox/VTListboxLabel.vue';
28
+ import VTListboxList from './src/components/Listbox/VTListboxList.vue';
29
+ import VTListboxSearch from './src/components/Listbox/VTListboxSearch.vue';
30
+ import VTListboxTrigger from './src/components/Listbox/VTListboxTrigger.vue';
31
+ import VTSpinner from './src/components/Spinner/VTSpinner.vue';
32
+ import VTInput from './src/components/Form/VTInput.vue';
33
+ import VTProgressBar from './src/components/ProgressBar/VTProgressBar.vue';
34
+ import VTTextarea from './src/components/Textarea/VTTextarea.vue';
35
+ import VTTab from './src/components/Tabs/VTTab.vue';
36
+ import VTTabGroup from './src/components/Tabs/VTTabGroup.vue';
37
+ import VTTabList from './src/components/Tabs/VTTabList.vue';
38
+ import VTTabPanel from './src/components/Tabs/VTTabPanel.vue';
39
+ import VTTabPanels from './src/components/Tabs/VTTabPanels.vue';
40
+ import VTDialog from './src/components/Dialog/VTDialog.vue';
41
+ import VTDialogClose from './src/components/Dialog/VTDialogClose.vue';
42
+ import VTDialogContent from './src/components/Dialog/VTDialogContent.vue';
43
+ import VTDialogFooter from './src/components/Dialog/VTDialogFooter.vue';
44
+ import VTDialogHeader from './src/components/Dialog/VTDialogHeader.vue';
45
+ import VTDialogMain from './src/components/Dialog/VTDialogMain.vue';
46
+ import VTDialogOverlay from './src/components/Dialog/VTDialogOverlay.vue';
47
+ import VTDialogTitle from './src/components/Dialog/VTDialogTitle.vue';
48
+ import VTDrawer from './src/components/Drawer/VTDrawer.vue';
49
+ import VTDrawerClose from './src/components/Drawer/VTDrawerClose.vue';
50
+ import VTDrawerContent from './src/components/Drawer/VTDrawerContent.vue';
51
+ import VTDrawerFooter from './src/components/Drawer/VTDrawerFooter.vue';
52
+ import VTDrawerHeader from './src/components/Drawer/VTDrawerHeader.vue';
53
+ import VTDrawerTitle from './src/components/Drawer/VTDrawerTitle.vue';
54
+ import VTDrawerMain from './src/components/Drawer/VTDrawerMain.vue';
55
+ import VTDrawerOverlay from './src/components/Drawer/VTDrawerOverlay.vue';
56
+ import VTDisclosure from './src/components/Disclosure/VTDisclosure.vue';
57
+ import VTDisclosureDetails from './src/components/Disclosure/VTDisclosureDetails.vue';
58
+ import VTDisclosureHeader from './src/components/Disclosure/VTDisclosureHeader.vue';
59
+ import VTDisclosureIcon from './src/components/Disclosure/VTDisclosureIcon.vue';
60
+ import VTDisclosureContent from './src/components/Disclosure/VTDisclosureContent.vue';
61
+ import VTSkeleton from './src/components/Skeleton/VTSkeleton.vue';
62
+ import VTSkeletonItem from './src/components/Skeleton/VTSkeletonItem.vue';
67
63
 
68
64
  export {
69
65
  VTAvatar,
@@ -98,14 +94,8 @@ export {
98
94
  VTListboxTrigger,
99
95
  VTButton,
100
96
  VTInput,
101
- VTInputIcon,
102
- VTInputPassword,
103
- VTInputDate,
104
- VTInputFile,
105
- VTInputUpload,
106
97
  VTProgressBar,
107
98
  VTTextarea,
108
- VTModal,
109
99
  VTTab,
110
100
  VTTabGroup,
111
101
  VTTabList,
@@ -132,4 +122,6 @@ export {
132
122
  VTDisclosureHeader,
133
123
  VTDisclosureIcon,
134
124
  VTDisclosureContent,
125
+ VTSkeleton,
126
+ VTSkeletonItem,
135
127
  };
@@ -10,22 +10,17 @@ export const floatingUiContentMixin = {
10
10
  type: Boolean,
11
11
  default: false,
12
12
  },
13
- floatingUiClass: {
14
- type: [String, Function],
15
- default: null,
16
- },
17
13
  },
18
14
 
19
15
  data() {
20
16
  return {
21
17
  el: null,
22
- isMousemove: false,
23
18
  visible: false,
24
19
  };
25
20
  },
26
21
 
27
22
  mounted() {
28
- document.addEventListener('click', (e) => this.onDocumentClick(e));
23
+ document.addEventListener('click', this.onDocumentClick);
29
24
  },
30
25
 
31
26
  destroyed() {
@@ -79,22 +74,6 @@ export const floatingUiContentMixin = {
79
74
  }
80
75
  },
81
76
 
82
- // Mousemove instead of mouseover to support keyboard navigation.
83
- // The problem with mouseover is that when scrolling (scrollIntoView),
84
- // mouseover event gets triggered.
85
- setMousemove() {
86
- this.isMousemove = true;
87
- },
88
-
89
- unsetMousemove() {
90
- this.isMousemove = false;
91
- },
92
-
93
- getMousemove() {
94
- return this.isMousemove;
95
- },
96
-
97
- //
98
77
  setActiveDescedant(id) {
99
78
  this.activeDescedant = id;
100
79
  },
@@ -19,10 +19,6 @@ export const floatingUiItemMixin = {
19
19
  return this.apiInjected().items;
20
20
  },
21
21
 
22
- el() {
23
- return this.$el;
24
- },
25
-
26
22
  componentContent() {
27
23
  return this.apiInjected().componentContent;
28
24
  },
@@ -36,7 +32,7 @@ export const floatingUiItemMixin = {
36
32
  // default styles
37
33
  this.headless
38
34
  ? `${this.componentName}`
39
- : 'relative z-10 flex items-center gap-2 px-3 py-2 text-inherit no-underline',
35
+ : 'relative z-10 flex items-center gap-2 px-3 py-2 text-inherit no-underline cursor-pointer',
40
36
  // disabled state styles
41
37
  this.headless
42
38
  ? this.disabled
@@ -51,7 +47,7 @@ export const floatingUiItemMixin = {
51
47
  ? `${this.componentName}--selected`
52
48
  : null
53
49
  : this.selected
54
- ? 'bg-secondary-200/10'
50
+ ? 'bg-gray-200'
55
51
  : null,
56
52
  ];
57
53
  },
@@ -62,20 +58,24 @@ export const floatingUiItemMixin = {
62
58
  index: null,
63
59
  selected: false,
64
60
  tabIndex: 0,
61
+ eventType: null,
65
62
  };
66
63
  },
67
64
 
68
65
  watch: {
69
66
  selected(newValue) {
70
- if (!newValue || !this.componentContent) return;
67
+ if (!newValue || !this.componentContent) {
68
+ return;
69
+ }
71
70
 
72
71
  this.componentContent.setActiveDescedant(this.id);
73
72
 
74
- const isMousemove = this.componentContent.getMousemove();
75
-
76
- if (!isMousemove) {
77
- this.el.scrollIntoView({ block: 'nearest' });
73
+ // do not scroll into view if it's a mouse event
74
+ if (this.eventType && this.eventType.includes('mouse')) {
75
+ return;
78
76
  }
77
+
78
+ this.$el.scrollIntoView({ block: 'nearest' });
79
79
  },
80
80
  },
81
81
 
@@ -84,37 +84,52 @@ export const floatingUiItemMixin = {
84
84
  this.addMouseEventListeners();
85
85
  },
86
86
 
87
- beforeDestroy() {
87
+ beforeUnmount() {
88
88
  this.apiInjected().unregisterItem(this.id);
89
89
  this.removeMouseEventListeners();
90
90
  },
91
91
 
92
92
  methods: {
93
93
  init() {
94
+ this.index = this.items.length;
95
+
94
96
  const item = {
95
97
  id: this.id,
98
+ text: '',
96
99
  select: this.select,
97
100
  unselect: this.unselect,
101
+ isSelected: this.isSelected,
98
102
  focus: this.focus,
99
103
  onClick: this.onClick,
100
104
  };
101
-
105
+
102
106
  this.apiInjected().registerItem(item);
103
-
104
- this.index = this.items.length - 1;
105
107
  },
106
108
 
109
+ /**
110
+ * mousemove and mouseleave events will be attached to
111
+ * the element here instead of using vue @mousemove
112
+ * and @mouseleave in the element since they did
113
+ * not worker properly
114
+ */
107
115
  addMouseEventListeners() {
108
- this.el.addEventListener('mousemove', this.onMousemove);
109
- this.el.addEventListener('mouseleave', this.onMouseleave);
116
+ this.$el.addEventListener('mousemove', this.onMousemove);
117
+ this.$el.addEventListener('mouseleave', this.onMouseleave);
110
118
  },
111
119
 
120
+ /**
121
+ * remove the mousemove and mouseleave added for
122
+ * avoiding memory leaks, if @mousemove and
123
+ * @mouseleave were in the element, this
124
+ * wound't be needed
125
+ */
112
126
  removeMouseEventListeners() {
113
- this.el.removeEventListener('mousemove', this.onMousemove);
114
- this.el.removeEventListener('mouseleave', this.onMouseleave);
127
+ this.$el.removeEventListener('mousemove', this.onMousemove);
128
+ this.$el.removeEventListener('mouseleave', this.onMouseleave);
115
129
  },
116
130
 
117
- select() {
131
+ select(eventType) {
132
+ this.eventType = eventType;
118
133
  this.selected = true;
119
134
  },
120
135
 
@@ -122,59 +137,84 @@ export const floatingUiItemMixin = {
122
137
  this.selected = false;
123
138
  },
124
139
 
140
+ isSelected() {
141
+ return this.selected;
142
+ },
143
+
125
144
  focus() {
126
- if (!this.el) return;
145
+ if (!this.$el) return;
127
146
 
128
147
  this.tabIndex = -1;
129
148
  this.selected = true;
130
- this.el.focus();
149
+ this.$el.focus();
131
150
  },
132
151
 
133
152
  focusFirstItem() {
134
- this.setFocusToItem(0);
153
+ const selectedIndex = this.getItemSelectedIndex();
154
+ const newSelectedIndex = 0;
155
+
156
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
135
157
  },
136
158
 
137
159
  focusLastItem() {
138
- this.setFocusToItem(this.items.length - 1);
160
+ const selectedIndex = this.getItemSelectedIndex();
161
+ const newSelectedIndex = this.items.length - 1;
162
+
163
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
139
164
  },
140
165
 
141
166
  /**
142
- * Focus the previous item in the menu.
143
- * If is the first item, jump to the last item.
167
+ * Focus the next item in the menu.
168
+ * If is the last item, jump to the first item.
144
169
  */
145
- focusPreviousItem() {
146
- const isLast = this.index === this.items.length - 1;
147
- const goToIndex = isLast ? 0 : this.index + 1;
170
+ focusNextItem() {
171
+ const selectedIndex = this.getItemSelectedIndex();
172
+ const isLast = selectedIndex === this.items.length - 1;
173
+ const firstItemIndex = 0;
174
+ const nextItemIndex = selectedIndex + 1;
175
+ const newSelectedIndex = isLast ? firstItemIndex : nextItemIndex;
148
176
 
149
- this.setFocusToItem(goToIndex);
177
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
150
178
  },
151
179
 
152
180
  /**
153
- * Focus the next item in the menu.
154
- * If is the last item, jump to the first item.
181
+ * Focus the previous item in the menu.
182
+ * If is the first item, jump to the last item.
155
183
  */
156
- focusNextItem() {
157
- const isFirst = this.index === 0;
158
- const goToIndex = isFirst ? this.items.length - 1 : this.index - 1;
184
+ focusPreviousItem() {
185
+ const selectedIndex = this.getItemSelectedIndex();
186
+ const isFirst = selectedIndex === 0;
187
+ const lastItemIndex = this.items.length - 1;
188
+ const previousItemIndex = selectedIndex - 1;
189
+ const newSelectedIndex = isFirst ? lastItemIndex : previousItemIndex;
159
190
 
160
- this.setFocusToItem(goToIndex);
191
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
161
192
  },
162
193
 
163
194
  /**
164
- * Focus item by remove its tabindex and calling
195
+ * Focus/select item by removing its tabindex and calling
165
196
  * focus to the element.
166
197
  *
167
- * @param {Number, String} goToIndex
198
+ * @param {Number, String} selectedIndex
199
+ * @param {Number, String} newSelectedIndex
168
200
  */
169
- setFocusToItem(goToIndex) {
201
+ setFocusToItem(selectedIndex, newSelectedIndex) {
170
202
  this.tabIndex = 0;
171
- this.selected = false;
172
203
 
173
- // set all selected to false
174
- this.items.forEach((item) => item.unselect());
204
+ // before focusing, let's unselect selected
205
+ // item that were previously focused
206
+ if (selectedIndex >= 0) {
207
+ this.items[selectedIndex].unselect();
208
+ }
175
209
 
176
- // focus item
177
- this.items[goToIndex].focus();
210
+ // focus new item
211
+ if (this.items[newSelectedIndex]) {
212
+ this.items[newSelectedIndex].focus();
213
+ }
214
+ },
215
+
216
+ getItemSelectedIndex() {
217
+ return this.items.findIndex((item) => item.isSelected());
178
218
  },
179
219
 
180
220
  leaveMenu() {
@@ -189,7 +229,10 @@ export const floatingUiItemMixin = {
189
229
  return;
190
230
  }
191
231
 
192
- this.value ? this.apiInjected().emit(this.value) : this.$emit('click');
232
+ this.value !== undefined
233
+ ? this.apiInjected().emit(this.value)
234
+ : this.$emit('click');
235
+
193
236
  this.$nextTick(() => this.leaveMenu());
194
237
  },
195
238
 
@@ -197,20 +240,27 @@ export const floatingUiItemMixin = {
197
240
  this.leaveMenu();
198
241
  },
199
242
 
200
- onMousemove() {
243
+ onMousemove(event) {
201
244
  if (this.selected) {
202
245
  return;
203
246
  }
204
247
 
205
- this.items.forEach((item) => item.unselect());
248
+ // unselect all items before selecting new one
249
+ for (const item of this.items) {
250
+ item.unselect();
251
+ }
206
252
 
207
- this.select();
208
- this.componentContent.setMousemove();
253
+ /**
254
+ * Select item passing the event type to decide if
255
+ * scrolling will be disabled or not. It is
256
+ * expected that on mouse move event, the scroll
257
+ * doesn't happen automatically.
258
+ */
259
+ this.select(event.type);
209
260
  },
210
261
 
211
262
  onMouseleave() {
212
263
  this.unselect();
213
- this.componentContent.unsetMousemove();
214
264
  },
215
265
  },
216
- };
266
+ };
@@ -2,9 +2,9 @@ import { computePosition, flip, shift, offset, size } from '@floating-ui/dom';
2
2
 
3
3
  export const floatingUiMixin = {
4
4
  props: {
5
- placement: {
6
- type: String,
7
- default: 'bottom-start',
5
+ offset: {
6
+ type: [Number, String],
7
+ default: 5,
8
8
  },
9
9
  },
10
10
 
@@ -40,22 +40,20 @@ export const floatingUiMixin = {
40
40
  },
41
41
 
42
42
  positionContentToTrigger() {
43
- // console.log(window.innerWidth)
44
-
45
43
  const trigger = document.getElementById(this.componentTrigger.id);
46
44
  const content = document.getElementById(this.componentContent.id);
45
+ const minWidthLimit = Number(this.floatingUiMinWidth);
47
46
 
48
47
  computePosition(trigger, content, {
49
48
  placement: this.placement,
50
49
  middleware: [
51
- offset(6),
50
+ offset(Number(this.offset)),
52
51
  flip(),
53
52
  shift({ padding: 5 }),
54
53
  size({
55
54
  apply({ rects }) {
56
- // the min width to floating uis should be 200
57
- // since less than that can look not as nice
58
- const minWidthLimit = 200;
55
+ if (!minWidthLimit) return;
56
+
59
57
  const width = rects.reference.width;
60
58
  const minWidth = width < minWidthLimit ? minWidthLimit : width;
61
59
 
@@ -1,9 +1,9 @@
1
- import { formControlMixin } from '../mixins/form-control';
1
+ import { formControlMixin, formControlStyleMixin } from '../mixins/form-control';
2
2
 
3
3
  export const formControlIconMixin = {
4
4
  inheritAttrs: false,
5
5
 
6
- mixins: [formControlMixin],
6
+ mixins: [formControlMixin, formControlStyleMixin],
7
7
 
8
8
  data() {
9
9
  return {
@@ -43,11 +43,11 @@ export const formControlIconMixin = {
43
43
  this.headless
44
44
  ? null
45
45
  : this.isLeft
46
- ? 'left-0'
46
+ ? 'left-1'
47
47
  : this.isRight
48
- ? 'right-0'
48
+ ? 'right-1'
49
49
  : null,
50
50
  ];
51
51
  },
52
52
  },
53
- };
53
+ };
@@ -1,9 +1,4 @@
1
1
  export const formControlMixin = {
2
- model: {
3
- prop: 'value',
4
- event: 'input',
5
- },
6
-
7
2
  props: {
8
3
  disabled: {
9
4
  type: Boolean,
@@ -13,7 +8,7 @@ export const formControlMixin = {
13
8
  type: Boolean,
14
9
  default: false,
15
10
  },
16
- value: {
11
+ modelValue: {
17
12
  type: [String, Number, Object, Array],
18
13
  default: null,
19
14
  },
@@ -24,32 +19,40 @@ export const formControlMixin = {
24
19
  },
25
20
 
26
21
  computed: {
27
- listeners() {
22
+ attrsComputed() {
28
23
  // `Object.assign` merges objects together to form a new object
29
24
  return Object.assign(
30
25
  {},
31
26
  // We add all the listeners from the parent
32
- this.$listeners,
27
+ this.$attrs,
33
28
  // Then we can add custom listeners or override the
34
29
  // behavior of some listeners.
35
30
  {
36
31
  // This ensures that the component works with v-model
37
- input: (event) => {
32
+ onInput: (event) => {
38
33
  // if (this.lazy) return;
39
- this.$emit('input', event.target.value);
34
+ this.$emit('update:modelValue', event.target.value);
40
35
  },
41
- blur: (event) => {
36
+ onBlur: (event) => {
42
37
  this.$emit('blur', event);
43
38
  },
44
39
  }
45
40
  );
46
41
  },
47
42
 
43
+ isError() {
44
+ return this.variant === 'error';
45
+ },
46
+ },
47
+ };
48
+
49
+ export const formControlStyleMixin = {
50
+ computed: {
48
51
  classComputed() {
49
52
  return [
50
53
  this.headless
51
54
  ? `${this.name}`
52
- : 'leading-0 flex w-full max-w-full appearance-none items-center justify-between gap-3 rounded border border-solid px-3 py-2 font-inherit text-base text-inherit file:hidden focus:border-secondary-200',
55
+ : 'leading-0 flex outline-none w-full max-w-full appearance-none items-center justify-between rounded border border-solid px-3 py-2 font-inherit text-base text-inherit file:hidden focus:border-secondary-200 appearance-none',
53
56
  // variant styles
54
57
  this.headless
55
58
  ? `${this.name}--${this.variant}`
@@ -61,12 +64,8 @@ export const formControlMixin = {
61
64
  ? null
62
65
  : this.name === 'textarea'
63
66
  ? 'min-h-10' // limit it because input type number height can be different from other input types
64
- : 'h-10',
67
+ : 'h-12 md:h-10',
65
68
  ];
66
69
  },
67
-
68
- isError() {
69
- return this.variant === 'error';
70
- },
71
70
  },
72
- };
71
+ };