@veritree/ui 0.21.1-9 → 0.22.0-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 (76) hide show
  1. package/.prettierrc +2 -1
  2. package/index.js +64 -68
  3. package/mixins/floating-ui-content.js +1 -22
  4. package/mixins/floating-ui-item.js +101 -57
  5. package/mixins/floating-ui.js +5 -14
  6. package/mixins/form-control-icon.js +53 -0
  7. package/mixins/form-control.js +17 -18
  8. package/nuxt.js +30 -23
  9. package/package.json +8 -4
  10. package/src/components/Alert/VTAlert.vue +55 -14
  11. package/src/components/Button/VTButton.vue +20 -7
  12. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  13. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  14. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  15. package/src/components/Dialog/VTDialog.vue +22 -32
  16. package/src/components/Dialog/VTDialogClose.vue +19 -25
  17. package/src/components/Dialog/VTDialogContent.vue +24 -19
  18. package/src/components/Dialog/VTDialogFooter.vue +11 -16
  19. package/src/components/Dialog/VTDialogHeader.vue +16 -18
  20. package/src/components/Dialog/VTDialogMain.vue +11 -18
  21. package/src/components/Dialog/VTDialogOverlay.vue +14 -18
  22. package/src/components/Dialog/VTDialogTitle.vue +10 -7
  23. package/src/components/Disclosure/VTDisclosureContent.vue +1 -1
  24. package/src/components/Disclosure/VTDisclosureDetails.vue +1 -1
  25. package/src/components/Disclosure/VTDisclosureHeader.vue +2 -2
  26. package/src/components/Disclosure/VTDisclosureIcon.vue +1 -1
  27. package/src/components/Drawer/VTDrawer.vue +6 -15
  28. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  29. package/src/components/Drawer/VTDrawerContent.vue +9 -9
  30. package/src/components/Drawer/VTDrawerFooter.vue +3 -3
  31. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  32. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  33. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  34. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  35. package/src/components/DropdownMenu/VTDropdownMenu.vue +19 -0
  36. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +14 -6
  37. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  38. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +2 -2
  39. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  40. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +1 -3
  41. package/src/components/Form/VTFormFeedback.vue +11 -5
  42. package/src/components/Form/VTFormGroup.vue +5 -7
  43. package/src/components/Form/VTFormLabel.vue +22 -0
  44. package/src/components/Form/VTFormRow.vue +5 -0
  45. package/src/components/Form/VTInput.vue +9 -9
  46. package/src/components/Form/VTInputIcon.vue +35 -0
  47. package/src/components/Form/VTInputPassword.vue +55 -0
  48. package/src/components/Form/VTTextarea.vue +1 -1
  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 +10 -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 +4 -3
  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/Form/VTInputQty.vue +0 -165
  71. package/src/components/Input/VTInput.vue +0 -82
  72. package/src/components/Input/VTInputDate.vue +0 -36
  73. package/src/components/Input/VTInputFile.vue +0 -60
  74. package/src/components/Input/VTInputUpload.vue +0 -54
  75. package/src/components/Modal/VTModal.vue +0 -69
  76. package/src/utils/genId.js +0 -13
package/.prettierrc CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "semi": true,
3
- "singleQuote": true
3
+ "singleQuote": true,
4
+ "quoteProps": "preserve"
4
5
  }
package/index.js CHANGED
@@ -1,67 +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 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/Input/VTInput.vue";
33
- import VTInputDate from "./src/components/Input/VTInputDate.vue";
34
- import VTInputFile from "./src/components/Input/VTInputFile.vue";
35
- import VTInputUpload from "./src/components/Input/VTInputUpload.vue";
36
- import VTProgressBar from "./src/components/ProgressBar/VTProgressBar.vue";
37
- import VTTextarea from "./src/components/Textarea/VTTextarea.vue";
38
- import VTModal from "./src/components/Modal/VTModal.vue";
39
- import VTTab from "./src/components/Tabs/VTTab.vue";
40
- import VTTabGroup from "./src/components/Tabs/VTTabGroup.vue";
41
- import VTTabList from "./src/components/Tabs/VTTabList.vue";
42
- import VTTabPanel from "./src/components/Tabs/VTTabPanel.vue";
43
- import VTTabPanels from "./src/components/Tabs/VTTabPanels.vue";
44
- import VTDialog from "./src/components/Dialog/VTDialog.vue";
45
- import VTDialogClose from "./src/components/Dialog/VTDialogClose.vue";
46
- import VTDialogContent from "./src/components/Dialog/VTDialogContent.vue";
47
- import VTDialogFooter from "./src/components/Dialog/VTDialogFooter.vue";
48
- import VTDialogHeader from "./src/components/Dialog/VTDialogHeader.vue";
49
- import VTDialogMain from "./src/components/Dialog/VTDialogMain.vue";
50
- import VTDialogOverlay from "./src/components/Dialog/VTDialogOverlay.vue";
51
- import VTDialogTitle from "./src/components/Dialog/VTDialogTitle.vue";
52
- import VTDrawer from "./src/components/Drawer/VTDrawer.vue";
53
- import VTDrawerClose from "./src/components/Drawer/VTDrawerClose.vue";
54
- import VTDrawerContent from "./src/components/Drawer/VTDrawerContent.vue";
55
- import VTDrawerFooter from "./src/components/Drawer/VTDrawerFooter.vue";
56
- import VTDrawerHeader from "./src/components/Drawer/VTDrawerHeader.vue";
57
- import VTDrawerTitle from "./src/components/Drawer/VTDrawerTitle.vue";
58
- import VTDrawerMain from "./src/components/Drawer/VTDrawerMain.vue";
59
- import VTDrawerOverlay from "./src/components/Drawer/VTDrawerOverlay.vue";
60
- import VTDisclosure from "./src/components/Disclosure/VTDisclosure.vue";
61
- import VTDisclosureDetails from "./src/components/Disclosure/VTDisclosureDetails.vue";
62
- import VTDisclosureHeader from "./src/components/Disclosure/VTDisclosureHeader.vue";
63
- import VTDisclosureIcon from "./src/components/Disclosure/VTDisclosureIcon.vue";
64
- 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';
65
63
 
66
64
  export {
67
65
  VTAvatar,
@@ -96,12 +94,8 @@ export {
96
94
  VTListboxTrigger,
97
95
  VTButton,
98
96
  VTInput,
99
- VTInputDate,
100
- VTInputFile,
101
- VTInputUpload,
102
97
  VTProgressBar,
103
98
  VTTextarea,
104
- VTModal,
105
99
  VTTab,
106
100
  VTTabGroup,
107
101
  VTTabList,
@@ -128,4 +122,6 @@ export {
128
122
  VTDisclosureHeader,
129
123
  VTDisclosureIcon,
130
124
  VTDisclosureContent,
125
+ VTSkeleton,
126
+ VTSkeletonItem,
131
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
  },
@@ -1,10 +1,4 @@
1
- import FloatingUiItem from '../src/components/Utils/FloatingUiItem.vue';
2
-
3
1
  export const floatingUiItemMixin = {
4
- components: {
5
- FloatingUiItem,
6
- },
7
-
8
2
  props: {
9
3
  headless: {
10
4
  type: Boolean,
@@ -25,10 +19,6 @@ export const floatingUiItemMixin = {
25
19
  return this.apiInjected().items;
26
20
  },
27
21
 
28
- el() {
29
- return this.$el;
30
- },
31
-
32
22
  componentContent() {
33
23
  return this.apiInjected().componentContent;
34
24
  },
@@ -42,7 +32,7 @@ export const floatingUiItemMixin = {
42
32
  // default styles
43
33
  this.headless
44
34
  ? `${this.componentName}`
45
- : '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',
46
36
  // disabled state styles
47
37
  this.headless
48
38
  ? this.disabled
@@ -57,7 +47,7 @@ export const floatingUiItemMixin = {
57
47
  ? `${this.componentName}--selected`
58
48
  : null
59
49
  : this.selected
60
- ? 'bg-secondary-200/10'
50
+ ? 'bg-gray-200'
61
51
  : null,
62
52
  ];
63
53
  },
@@ -68,20 +58,24 @@ export const floatingUiItemMixin = {
68
58
  index: null,
69
59
  selected: false,
70
60
  tabIndex: 0,
61
+ eventType: null,
71
62
  };
72
63
  },
73
64
 
74
65
  watch: {
75
66
  selected(newValue) {
76
- if (!newValue || !this.componentContent) return;
67
+ if (!newValue || !this.componentContent) {
68
+ return;
69
+ }
77
70
 
78
71
  this.componentContent.setActiveDescedant(this.id);
79
72
 
80
- const isMousemove = this.componentContent.getMousemove();
81
-
82
- if (!isMousemove) {
83
- 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;
84
76
  }
77
+
78
+ this.$el.scrollIntoView({ block: 'nearest' });
85
79
  },
86
80
  },
87
81
 
@@ -90,37 +84,52 @@ export const floatingUiItemMixin = {
90
84
  this.addMouseEventListeners();
91
85
  },
92
86
 
93
- beforeDestroy() {
87
+ beforeUnmount() {
94
88
  this.apiInjected().unregisterItem(this.id);
95
89
  this.removeMouseEventListeners();
96
90
  },
97
91
 
98
92
  methods: {
99
93
  init() {
94
+ this.index = this.items.length;
95
+
100
96
  const item = {
101
97
  id: this.id,
98
+ text: '',
102
99
  select: this.select,
103
100
  unselect: this.unselect,
101
+ isSelected: this.isSelected,
104
102
  focus: this.focus,
105
103
  onClick: this.onClick,
106
104
  };
107
-
105
+
108
106
  this.apiInjected().registerItem(item);
109
-
110
- this.index = this.items.length - 1;
111
107
  },
112
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
+ */
113
115
  addMouseEventListeners() {
114
- this.el.addEventListener('mousemove', this.onMousemove);
115
- this.el.addEventListener('mouseleave', this.onMouseleave);
116
+ this.$el.addEventListener('mousemove', this.onMousemove);
117
+ this.$el.addEventListener('mouseleave', this.onMouseleave);
116
118
  },
117
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
+ */
118
126
  removeMouseEventListeners() {
119
- this.el.removeEventListener('mousemove', this.onMousemove);
120
- this.el.removeEventListener('mouseleave', this.onMouseleave);
127
+ this.$el.removeEventListener('mousemove', this.onMousemove);
128
+ this.$el.removeEventListener('mouseleave', this.onMouseleave);
121
129
  },
122
130
 
123
- select() {
131
+ select(eventType) {
132
+ this.eventType = eventType;
124
133
  this.selected = true;
125
134
  },
126
135
 
@@ -128,59 +137,84 @@ export const floatingUiItemMixin = {
128
137
  this.selected = false;
129
138
  },
130
139
 
140
+ isSelected() {
141
+ return this.selected;
142
+ },
143
+
131
144
  focus() {
132
- if (!this.el) return;
145
+ if (!this.$el) return;
133
146
 
134
147
  this.tabIndex = -1;
135
148
  this.selected = true;
136
- this.el.focus();
149
+ this.$el.focus();
137
150
  },
138
151
 
139
152
  focusFirstItem() {
140
- this.setFocusToItem(0);
153
+ const selectedIndex = this.getItemSelectedIndex();
154
+ const newSelectedIndex = 0;
155
+
156
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
141
157
  },
142
158
 
143
159
  focusLastItem() {
144
- this.setFocusToItem(this.items.length - 1);
160
+ const selectedIndex = this.getItemSelectedIndex();
161
+ const newSelectedIndex = this.items.length - 1;
162
+
163
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
145
164
  },
146
165
 
147
166
  /**
148
- * Focus the previous item in the menu.
149
- * 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.
150
169
  */
151
- focusPreviousItem() {
152
- const isLast = this.index === this.items.length - 1;
153
- 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;
154
176
 
155
- this.setFocusToItem(goToIndex);
177
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
156
178
  },
157
179
 
158
180
  /**
159
- * Focus the next item in the menu.
160
- * 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.
161
183
  */
162
- focusNextItem() {
163
- const isFirst = this.index === 0;
164
- 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;
165
190
 
166
- this.setFocusToItem(goToIndex);
191
+ this.setFocusToItem(selectedIndex, newSelectedIndex);
167
192
  },
168
193
 
169
194
  /**
170
- * Focus item by remove its tabindex and calling
195
+ * Focus/select item by removing its tabindex and calling
171
196
  * focus to the element.
172
197
  *
173
- * @param {Number, String} goToIndex
198
+ * @param {Number, String} selectedIndex
199
+ * @param {Number, String} newSelectedIndex
174
200
  */
175
- setFocusToItem(goToIndex) {
201
+ setFocusToItem(selectedIndex, newSelectedIndex) {
176
202
  this.tabIndex = 0;
177
- this.selected = false;
178
203
 
179
- // set all selected to false
180
- 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
+ }
181
209
 
182
- // focus item
183
- 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());
184
218
  },
185
219
 
186
220
  leaveMenu() {
@@ -195,7 +229,10 @@ export const floatingUiItemMixin = {
195
229
  return;
196
230
  }
197
231
 
198
- 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
+
199
236
  this.$nextTick(() => this.leaveMenu());
200
237
  },
201
238
 
@@ -203,20 +240,27 @@ export const floatingUiItemMixin = {
203
240
  this.leaveMenu();
204
241
  },
205
242
 
206
- onMousemove() {
243
+ onMousemove(event) {
207
244
  if (this.selected) {
208
245
  return;
209
246
  }
210
247
 
211
- 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
+ }
212
252
 
213
- this.select();
214
- 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);
215
260
  },
216
261
 
217
262
  onMouseleave() {
218
263
  this.unselect();
219
- this.componentContent.unsetMousemove();
220
264
  },
221
265
  },
222
- };
266
+ };
@@ -1,13 +1,6 @@
1
1
  import { computePosition, flip, shift, offset, size } from '@floating-ui/dom';
2
2
 
3
3
  export const floatingUiMixin = {
4
- props: {
5
- placement: {
6
- type: String,
7
- default: 'bottom-start',
8
- },
9
- },
10
-
11
4
  data() {
12
5
  return {
13
6
  component: null,
@@ -40,22 +33,20 @@ export const floatingUiMixin = {
40
33
  },
41
34
 
42
35
  positionContentToTrigger() {
43
- // console.log(window.innerWidth)
44
-
45
36
  const trigger = document.getElementById(this.componentTrigger.id);
46
37
  const content = document.getElementById(this.componentContent.id);
38
+ const minWidthLimit = Number(this.floatingUiMinWidth);
47
39
 
48
40
  computePosition(trigger, content, {
49
41
  placement: this.placement,
50
42
  middleware: [
51
- offset(6),
43
+ offset(5),
52
44
  flip(),
53
45
  shift({ padding: 5 }),
54
46
  size({
55
47
  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;
48
+ if (!minWidthLimit) return;
49
+
59
50
  const width = rects.reference.width;
60
51
  const minWidth = width < minWidthLimit ? minWidthLimit : width;
61
52
 
@@ -73,4 +64,4 @@ export const floatingUiMixin = {
73
64
  });
74
65
  },
75
66
  },
76
- };
67
+ };
@@ -0,0 +1,53 @@
1
+ import { formControlMixin, formControlStyleMixin } from '../mixins/form-control';
2
+
3
+ export const formControlIconMixin = {
4
+ inheritAttrs: false,
5
+
6
+ mixins: [formControlMixin, formControlStyleMixin],
7
+
8
+ data() {
9
+ return {
10
+ name: 'input',
11
+ };
12
+ },
13
+
14
+ computed: {
15
+ isLeft() {
16
+ return this.iconPlacement === 'left';
17
+ },
18
+
19
+ isRight() {
20
+ return this.iconPlacement === 'right';
21
+ },
22
+
23
+ classComputedWrapper() {
24
+ return [
25
+ this.headless ? 'form-control-wrapper' : 'relative',
26
+ // placement styles
27
+ this.headless
28
+ ? `form-control-icon--${this.placement}`
29
+ : this.isLeft
30
+ ? '[&_input]:pl-9'
31
+ : this.isRight
32
+ ? '[&_input]:pr-9'
33
+ : null,
34
+ ];
35
+ },
36
+
37
+ classComputedWrapperIcon() {
38
+ return [
39
+ this.headless
40
+ ? 'form-control-wrapper__icon'
41
+ : `absolute top-0 bottom-0 flex w-9 justify-center items-center text-gray-400`,
42
+ // placement styles
43
+ this.headless
44
+ ? null
45
+ : this.isLeft
46
+ ? 'left-1'
47
+ : this.isRight
48
+ ? 'right-1'
49
+ : null,
50
+ ];
51
+ },
52
+ },
53
+ };