@veritree/ui 0.21.1-8 → 0.22.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.
@@ -3,30 +3,10 @@
3
3
  :is="as"
4
4
  :id="id"
5
5
  :to="to"
6
- :class="[
7
- // default styles
8
- headless
9
- ? 'dropdown-menu-item'
10
- : 'relative z-10 -mx-3 flex items-center gap-2 px-3 py-2 text-inherit no-underline hover:bg-secondary-200/10',
11
- // disabled state styles
12
- headless
13
- ? disabled
14
- ? 'listbox-item--disabled'
15
- : null
16
- : disabled
17
- ? 'pointer-events-none opacity-75'
18
- : null,
19
- // selected state styles
20
- headless
21
- ? selected
22
- ? 'lisbox-item--selected'
23
- : null
24
- : selected
25
- ? 'bg-secondary-200/10'
26
- : null,
27
- ]"
28
- :tabindex="tabIndex"
6
+ :class="classComputed"
29
7
  :aria-disabled="disabled"
8
+ :tabindex="tabIndex"
9
+ class="-mx-3"
30
10
  role="menuitem"
31
11
  @click.stop.prevent="onClick"
32
12
  @keydown.down.prevent="focusPreviousItem"
@@ -42,11 +22,13 @@
42
22
  </template>
43
23
 
44
24
  <script>
45
- import { genId } from '../../utils/ids';
25
+ import { floatingUiItemMixin } from '../../../mixins/floating-ui-item';
46
26
 
47
27
  export default {
48
28
  name: 'VTDropdownMenuItem',
49
29
 
30
+ mixins: [floatingUiItemMixin],
31
+
50
32
  inject: ['apiDropdownMenu'],
51
33
 
52
34
  props: {
@@ -58,139 +40,19 @@ export default {
58
40
  type: String,
59
41
  default: null,
60
42
  },
61
- disabled: {
62
- type: Boolean,
63
- default: false,
64
- },
65
- headless: {
66
- type: Boolean,
67
- default: false,
68
- },
69
43
  },
70
44
 
71
45
  data() {
72
46
  return {
73
- index: null,
74
- selected: false,
75
- tabIndex: 0,
47
+ apiInjected: this.apiDropdownMenu,
48
+ componentName: 'dropdown-menu-item',
76
49
  };
77
50
  },
78
51
 
79
52
  computed: {
80
- id() {
81
- return `dropdown-menu-item-${this.apiDropdownMenu().id}-${genId()}`;
82
- },
83
-
84
53
  as() {
85
54
  return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
86
55
  },
87
-
88
- items() {
89
- return this.apiDropdownMenu().items;
90
- },
91
-
92
- el() {
93
- return this.$el;
94
- },
95
-
96
- componentTrigger() {
97
- return this.apiDropdownMenu().componentTrigger;
98
- },
99
- },
100
-
101
- mounted() {
102
- const item = {
103
- select: this.select,
104
- unselect: this.unselect,
105
- focus: this.focus,
106
- };
107
-
108
- this.apiDropdownMenu().registerItem(item);
109
-
110
- this.index = this.items.length - 1;
111
- },
112
-
113
- methods: {
114
- select() {
115
- this.selected = true;
116
- },
117
-
118
- unselect() {
119
- this.selected = false;
120
- },
121
-
122
- focus() {
123
- if (!this.el) return;
124
-
125
- this.tabIndex = -1;
126
- this.selected = true;
127
- this.el.focus();
128
- },
129
-
130
- focusFirstItem() {
131
- this.setFocusToItem(0);
132
- },
133
-
134
- focusLastItem() {
135
- this.setFocusToItem(this.items.length - 1);
136
- },
137
-
138
- /**
139
- * Focus the previous item in the menu.
140
- * If is the first item, jump to the last item.
141
- */
142
- focusPreviousItem() {
143
- const isLast = this.index === this.items.length - 1;
144
- const goToIndex = isLast ? 0 : this.index + 1;
145
-
146
- this.setFocusToItem(goToIndex);
147
- },
148
-
149
- /**
150
- * Focus the next item in the menu.
151
- * If is the last item, jump to the first item.
152
- */
153
- focusNextItem() {
154
- const isFirst = this.index === 0;
155
- const goToIndex = isFirst ? this.items.length - 1 : this.index - 1;
156
-
157
- this.setFocusToItem(goToIndex);
158
- },
159
-
160
- /**
161
- * Focus item by remove its tabindex and calling
162
- * focus to the element.
163
- *
164
- * @param {Number, String} goToIndex
165
- */
166
- setFocusToItem(goToIndex) {
167
- this.tabIndex = 0;
168
- this.selected = false;
169
-
170
- // set all selected to false
171
- this.items.forEach((item) => item.unselect());
172
-
173
- // focus item
174
- this.items[goToIndex].focus();
175
- },
176
-
177
- leaveMenu() {
178
- if (this.componentTrigger) {
179
- this.componentTrigger.cancel();
180
- this.componentTrigger.focus();
181
- }
182
- },
183
-
184
- onKeyEsc() {
185
- this.leaveMenu();
186
- },
187
-
188
- onClick() {
189
- if (this.disabled) return;
190
-
191
- this.$emit('click');
192
- this.$nextTick(() => this.leaveMenu());
193
- },
194
56
  },
195
57
  };
196
58
  </script>
@@ -1,52 +1,40 @@
1
1
  <template>
2
2
  <input
3
- v-bind="$attrs"
4
- :class="[
5
- headless
6
- ? 'form-control'
7
- : 'border border-solid py-2 px-3 rounded text-inherit max-w-full',
8
- headless
9
- ? `form-control--${variant}`
10
- : isError
11
- ? 'border-error-300'
12
- : 'border-gray-300',
13
- ]"
3
+ :class="classComputed"
14
4
  :value="value"
15
- @input="$emit('input', $event.target.value)"
16
- @blur="$emit('blur')"
5
+ :disabled="disabled"
6
+ v-on="listeners"
17
7
  />
18
8
  </template>
19
9
 
20
10
  <script>
21
- export default {
22
- model: {
23
- prop: 'value',
24
- event: 'input',
25
- },
11
+ import { formControlMixin } from '../../../mixins/form-control';
26
12
 
27
- props: {
28
- disabled: {
29
- type: Boolean,
30
- default: false,
31
- },
32
- value: {
33
- type: [String, Number, Object, Array],
34
- default: null,
35
- },
36
- headless: {
37
- type: Boolean,
38
- default: false,
39
- },
40
- variant: {
41
- type: [String, Object, Function],
42
- default: '',
43
- },
44
- },
13
+ export default {
14
+ mixins: [formControlMixin],
45
15
 
46
- computed: {
47
- isError() {
48
- return this.variant === 'error';
49
- },
16
+ data() {
17
+ return {
18
+ name: 'input',
19
+ };
50
20
  },
51
21
  };
52
22
  </script>
23
+
24
+ <style scoped>
25
+ /* input[type='date']::-webkit-inner-spin-button,
26
+ input[type='date']::-webkit-calendar-picker-indicator {
27
+ position: absolute;
28
+ opacity: 0;
29
+ } */
30
+
31
+ input[type='number'] {
32
+ appearance: textfield;
33
+ }
34
+
35
+ input[type='number']::-webkit-inner-spin-button,
36
+ input[type='number']::-webkit-outer-spin-button {
37
+ appearance: none;
38
+ -webkit-appearance: none;
39
+ }
40
+ </style>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div :class="classComputedWrapper">
3
+ <input
4
+ :class="classComputed"
5
+ :value="value"
6
+ :disabled="disabled"
7
+ v-bind="$attrs"
8
+ v-on="listeners"
9
+ />
10
+ <div :class="classComputedWrapperIcon">
11
+ <component :is="icon" class="h-5 w-5" />
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { formControlIconMixin } from '../../../mixins/form-control-icon';
18
+
19
+ export default {
20
+ name: 'VTInputIcon',
21
+
22
+ mixins: [formControlIconMixin],
23
+
24
+ props: {
25
+ icon: {
26
+ type: String,
27
+ default: null,
28
+ required: true,
29
+ },
30
+ iconPlacement: {
31
+ type: String,
32
+ default: 'left',
33
+ },
34
+ },
35
+ };
36
+ </script>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <div :class="classComputedWrapper">
3
+ <input
4
+ :class="classComputed"
5
+ :value="value"
6
+ :disabled="disabled"
7
+ :type="reveal ? 'text' : 'password'"
8
+ v-bind="$attrs"
9
+ v-on="listeners"
10
+ />
11
+ <div :class="classComputedWrapperIcon">
12
+ <VTButton v-show="value.length" variant="icon" @click="reveal = !reveal">
13
+ <component :is="iconVisibility" class="h-5 w-5" />
14
+ </VTButton>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import { formControlIconMixin } from '../../../mixins/form-control-icon';
21
+
22
+ export default {
23
+ name: 'VTInputPassword',
24
+
25
+ mixins: [formControlIconMixin],
26
+
27
+ props: {
28
+ iconPlacement: {
29
+ type: String,
30
+ default: 'right',
31
+ },
32
+ },
33
+
34
+ data() {
35
+ return {
36
+ reveal: false,
37
+ };
38
+ },
39
+
40
+ computed: {
41
+ iconVisibility() {
42
+ return this.reveal ? 'IconVisibilityOn' : 'IconVisibilityOff';
43
+ },
44
+ },
45
+ };
46
+ </script>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <textarea
3
+ :class="classComputed"
4
+ :value="value"
5
+ :disabled="disabled"
6
+ v-on="listeners"
7
+ />
8
+ </template>
9
+
10
+ <script>
11
+ import { formControlMixin } from '../../../mixins/form-control';
12
+
13
+ export default {
14
+ mixins: [formControlMixin],
15
+
16
+ data() {
17
+ return {
18
+ name: 'textarea',
19
+ };
20
+ },
21
+ };
22
+ </script>
@@ -31,10 +31,10 @@ export default {
31
31
  this.search = search;
32
32
  };
33
33
 
34
- const registerList = (list) => {
35
- if (!list) return;
36
- this.list = list;
37
- };
34
+ // const registerList = (list) => {
35
+ // if (!list) return;
36
+ // this.list = list;
37
+ // };
38
38
 
39
39
  const registerItem = (item) => {
40
40
  if (!item) return;
@@ -56,13 +56,12 @@ export default {
56
56
  component: this.component,
57
57
  componentTrigger: this.componentTrigger,
58
58
  componentContent: this.componentContent,
59
- list: this.list,
60
59
  items: this.items,
61
60
  search: this.search,
62
61
  registerTrigger,
63
62
  registerContent,
64
63
  registerSearch,
65
- registerList,
64
+ // registerList,
66
65
  registerItem,
67
66
  unregisterItem,
68
67
  emit,
@@ -94,7 +93,6 @@ export default {
94
93
  return {
95
94
  componentId: genId(),
96
95
  search: null,
97
- list: null,
98
96
  items: [],
99
97
  };
100
98
  },
@@ -47,16 +47,13 @@ export default {
47
47
  id: this.id,
48
48
  show: this.show,
49
49
  hide: this.hide,
50
+ getMousemove: this.getMousemove,
51
+ setMousemove: this.setMousemove,
52
+ unsetMousemove: this.unsetMousemove,
50
53
  setActiveDescedant: this.setActiveDescedant,
51
54
  };
52
55
 
53
56
  this.apiListbox().registerContent(content);
54
57
  },
55
-
56
- methods: {
57
- setActiveDescedant(id) {
58
- this.activeDescedant = id;
59
- },
60
- },
61
58
  };
62
59
  </script>
@@ -1,28 +1,7 @@
1
1
  <template>
2
2
  <li
3
3
  :id="id"
4
- :class="[
5
- // default styles
6
- headless
7
- ? 'listbox-item'
8
- : 'relative z-10 flex items-center gap-2 px-3 py-2 text-inherit no-underline hover:bg-secondary-200/10',
9
- // disabled state styles
10
- headless
11
- ? disabled
12
- ? 'listbox-item--disabled'
13
- : null
14
- : disabled
15
- ? 'pointer-events-none opacity-75'
16
- : null,
17
- // selected state styles
18
- headless
19
- ? selected
20
- ? 'lisbox-item--selected'
21
- : null
22
- : selected
23
- ? 'bg-secondary-200/10'
24
- : null,
25
- ]"
4
+ :class="classComputed"
26
5
  :aria-disabled="disabled"
27
6
  :aria-selected="String(selected)"
28
7
  :tabindex="tabIndex"
@@ -38,28 +17,21 @@
38
17
  @mouseout="onMouseleave"
39
18
  @keydown.tab.prevent
40
19
  >
41
- <span class="truncate"><slot></slot></span>
20
+ <slot></slot>
42
21
  </li>
43
22
  </template>
44
23
 
45
24
  <script>
46
- import { scrollElementIntoView } from '../../utils/components';
47
- import { genId } from '../../utils/ids';
25
+ import { floatingUiItemMixin } from '../../../mixins/floating-ui-item';
48
26
 
49
27
  export default {
50
28
  name: 'VTListboxItem',
51
29
 
30
+ mixins: [floatingUiItemMixin],
31
+
52
32
  inject: ['apiListbox'],
53
33
 
54
34
  props: {
55
- headless: {
56
- type: Boolean,
57
- default: false,
58
- },
59
- disabled: {
60
- type: Boolean,
61
- default: false,
62
- },
63
35
  value: {
64
36
  type: [String, Number, Object, Array],
65
37
  required: true,
@@ -68,171 +40,14 @@ export default {
68
40
 
69
41
  data() {
70
42
  return {
71
- id: `listboxitem-${genId()}`,
72
- index: null,
73
- selected: false,
74
- tabIndex: 0,
43
+ apiInjected: this.apiListbox,
44
+ componentName: 'listbox-item',
75
45
  };
76
46
  },
77
47
 
78
48
  computed: {
79
- items() {
80
- return this.apiListbox().items;
81
- },
82
-
83
- el() {
84
- return this.$el;
85
- },
86
-
87
- componentTrigger() {
88
- return this.apiListbox().componentTrigger;
89
- },
90
-
91
- componentContent() {
92
- return this.apiListbox().componentContent;
93
- },
94
-
95
- list() {
96
- return this.apiListbox().list;
97
- },
98
-
99
49
  search() {
100
- return this.apiListbox().search;
101
- },
102
- },
103
-
104
- watch: {
105
- selected(newValue) {
106
- if (!newValue || !this.list) return;
107
-
108
- if (this.componentContent) {
109
- this.componentContent.setActiveDescedant(this.id);
110
- }
111
-
112
- const isMousemove = this.list.getMousemove();
113
-
114
- if (!isMousemove) {
115
- scrollElementIntoView(this.el, this.list.el);
116
- }
117
- },
118
- },
119
-
120
- mounted() {
121
- const item = {
122
- id: this.id,
123
- focus: this.focus,
124
- select: this.select,
125
- unselect: this.unselect,
126
- onClick: this.onClick,
127
- };
128
-
129
- this.apiListbox().registerItem(item);
130
-
131
- this.index = this.items.length - 1;
132
- },
133
-
134
- beforeDestroy() {
135
- this.apiListbox().unregisterItem(this.id);
136
- },
137
-
138
- methods: {
139
- select() {
140
- this.selected = true;
141
- },
142
-
143
- unselect() {
144
- this.selected = false;
145
- },
146
-
147
- focus() {
148
- if (!this.el) return;
149
-
150
- this.tabIndex = -1;
151
- this.selected = true;
152
- this.el.focus();
153
- },
154
-
155
- focusFirstItem() {
156
- this.setFocusToItem(0);
157
- },
158
-
159
- focusLastItem() {
160
- this.setFocusToItem(this.items.length - 1);
161
- },
162
-
163
- /**
164
- * Focus the previous item in the menu.
165
- * If is the first item, jump to the last item.
166
- */
167
- focusPreviousItem() {
168
- const isLast = this.index === this.items.length - 1;
169
- const goToIndex = isLast ? 0 : this.index + 1;
170
-
171
- this.setFocusToItem(goToIndex);
172
- },
173
-
174
- /**
175
- * Focus the next item in the menu.
176
- * If is the last item, jump to the first item.
177
- */
178
- focusNextItem() {
179
- const isFirst = this.index === 0;
180
- const goToIndex = isFirst ? this.items.length - 1 : this.index - 1;
181
-
182
- this.setFocusToItem(goToIndex);
183
- },
184
-
185
- /**
186
- * Focus item by remove its tabindex and calling
187
- * focus to the element.
188
- *
189
- * @param {Number, String} goToIndex
190
- */
191
- setFocusToItem(goToIndex) {
192
- this.tabIndex = 0;
193
- this.selected = false;
194
-
195
- const isMousemove = this.list.getMousemove();
196
-
197
- if (isMousemove) {
198
- this.list.unsetMousemove();
199
- this.items.forEach((item) => item.unselect());
200
- }
201
-
202
- this.items[goToIndex].focus();
203
- },
204
-
205
- /**
206
- * Hides componentContent/menu and focus on componentTrigger
207
- */
208
- leaveMenu() {
209
- if (this.componentTrigger) {
210
- this.componentTrigger.cancel();
211
- this.componentTrigger.focus();
212
- }
213
- },
214
-
215
- onKeyEsc() {
216
- this.leaveMenu();
217
- },
218
-
219
- onClick() {
220
- if (this.disabled) return;
221
-
222
- this.apiListbox().emit(this.value);
223
- this.$nextTick(() => this.leaveMenu());
224
- },
225
-
226
- onMousemove() {
227
- this.items.forEach((item) => item.unselect());
228
-
229
- this.select();
230
- this.list.setMousemove();
231
- },
232
-
233
- onMouseleave() {
234
- this.unselect();
235
- this.list.unsetMousemove();
50
+ return this.apiInjected().search;
236
51
  },
237
52
  },
238
53
  };