@volverjs/ui-vue 0.0.1 → 0.0.3-beta.2

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 (118) hide show
  1. package/README.md +17 -0
  2. package/auto-imports.d.ts +289 -0
  3. package/dist/components/VvButton/VvButton.es.js +159 -147
  4. package/dist/components/VvButton/VvButton.umd.js +1 -1
  5. package/dist/components/VvButton/VvButton.vue.d.ts +0 -8
  6. package/dist/components/VvButton/index.d.ts +4 -4
  7. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +36 -37
  8. package/dist/components/VvButtonGroup/VvButtonGroup.umd.js +1 -1
  9. package/dist/components/VvButtonGroup/VvButtonGroup.vue.d.ts +10 -10
  10. package/dist/components/VvButtonGroup/index.d.ts +5 -5
  11. package/dist/components/VvCombobox/VvCombobox.es.js +526 -345
  12. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  13. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +22 -0
  14. package/dist/components/VvCombobox/index.d.ts +13 -1
  15. package/dist/components/VvDropdown/VvDropdown.es.js +118 -109
  16. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  17. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +19 -0
  18. package/dist/components/VvDropdown/index.d.ts +12 -0
  19. package/dist/components/VvInputText/VvInputText.es.js +221 -213
  20. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  21. package/dist/components/VvInputText/VvInputText.vue.d.ts +13 -13
  22. package/dist/components/VvInputText/index.d.ts +5 -5
  23. package/dist/components/VvSelect/VvSelect.es.js +186 -167
  24. package/dist/components/VvSelect/VvSelect.umd.js +1 -1
  25. package/dist/components/VvSelect/VvSelect.vue.d.ts +23 -11
  26. package/dist/components/VvSelect/index.d.ts +10 -17
  27. package/dist/components/VvTextarea/VvTextarea.es.js +241 -277
  28. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  29. package/dist/components/VvTextarea/VvTextarea.vue.d.ts +12 -12
  30. package/dist/components/VvTextarea/index.d.ts +5 -5
  31. package/dist/components/VvTooltip/VvTooltip.es.js +28 -0
  32. package/dist/components/VvTooltip/VvTooltip.umd.js +1 -0
  33. package/dist/components/VvTooltip/VvTooltip.vue.d.ts +23 -0
  34. package/dist/components/VvTooltip/index.d.ts +18 -0
  35. package/dist/components/index.es.js +1046 -976
  36. package/dist/components/index.umd.js +1 -1
  37. package/dist/composables/group/types/IButtonGroupState.d.ts +1 -1
  38. package/dist/composables/group/types/IGroupState.d.ts +1 -1
  39. package/dist/composables/group/useInjectedGroupState.d.ts +1 -1
  40. package/dist/icons.es.js +3 -3
  41. package/dist/icons.umd.js +1 -1
  42. package/dist/index.es.js +1127 -1057
  43. package/dist/index.umd.js +1 -1
  44. package/dist/props/index.d.ts +35 -4
  45. package/dist/resolvers/unplugin.es.js +26 -24
  46. package/dist/resolvers/unplugin.umd.js +1 -1
  47. package/dist/stories/Button/Button.settings.d.ts +9 -11
  48. package/dist/stories/ButtonGroup/ButtonGroup.settings.d.ts +9 -0
  49. package/dist/stories/Combobox/Combobox.settings.d.ts +19 -0
  50. package/dist/stories/Dropdown/Dropdown.settings.d.ts +10 -0
  51. package/dist/stories/InputText/InputText.settings.d.ts +23 -23
  52. package/dist/stories/Select/Select.settings.d.ts +42 -23
  53. package/dist/stories/Textarea/Textarea.settings.d.ts +23 -23
  54. package/dist/stories/Tooltip/Tooltip.settings.d.ts +42 -0
  55. package/dist/stories/Tooltip/Tooltip.test.d.ts +2 -0
  56. package/dist/stories/argTypes.d.ts +50 -1
  57. package/package.json +31 -23
  58. package/src/assets/icons/detailed.json +1 -1
  59. package/src/assets/icons/normal.json +1 -1
  60. package/src/assets/icons/simple.json +1 -1
  61. package/src/components/VvButton/index.ts +28 -10
  62. package/src/components/VvButtonGroup/VvButtonGroup.vue +1 -1
  63. package/src/components/VvButtonGroup/index.ts +3 -6
  64. package/src/components/VvCombobox/VvCombobox.vue +45 -11
  65. package/src/components/VvCombobox/index.ts +6 -0
  66. package/src/components/VvDropdown/VvDropdown.vue +9 -6
  67. package/src/components/VvDropdown/index.ts +11 -1
  68. package/src/components/VvInputText/VvInputText.vue +10 -8
  69. package/src/components/VvSelect/VvSelect.vue +23 -1
  70. package/src/components/VvSelect/index.ts +8 -11
  71. package/src/components/VvTextarea/VvTextarea.vue +9 -21
  72. package/src/components/VvTooltip/VvTooltip.vue +17 -0
  73. package/src/components/VvTooltip/index.ts +21 -0
  74. package/src/composables/group/types/IButtonGroupState.ts +1 -1
  75. package/src/composables/group/types/IGroupState.ts +1 -1
  76. package/src/composables/group/useInjectedGroupState.ts +3 -3
  77. package/src/composables/useTextCount.ts +1 -1
  78. package/src/props/index.ts +33 -15
  79. package/src/resolvers/unplugin.ts +22 -13
  80. package/src/stories/Accordion/Accordion.stories.mdx +1 -1
  81. package/src/stories/AccordionGroup/AccordionGroup.stories.mdx +1 -1
  82. package/src/stories/AccordionGroup/AccordionGroupSlots.stories.mdx +1 -1
  83. package/src/stories/Badge/Badge.stories.mdx +1 -1
  84. package/src/stories/Breadcrumb/Breadcrumb.stories.mdx +1 -1
  85. package/src/stories/Breadcrumb/BreadcrumbSlots.stories.mdx +1 -1
  86. package/src/stories/Button/Button.settings.ts +2 -7
  87. package/src/stories/Button/Button.stories.mdx +1 -1
  88. package/src/stories/Button/ButtonModifiers.stories.mdx +2 -2
  89. package/src/stories/Button/ButtonSlots.stories.mdx +3 -3
  90. package/src/stories/ButtonGroup/ButtonGroup.settings.ts +6 -1
  91. package/src/stories/ButtonGroup/ButtonGroup.stories.mdx +1 -1
  92. package/src/stories/ButtonGroup/ButtonGroupSlots.stories.mdx +37 -0
  93. package/src/stories/ButtonGroup/ButtonGroupToggle.stories.mdx +12 -1
  94. package/src/stories/Card/Card.stories.mdx +1 -1
  95. package/src/stories/Card/CardSlots.stories.mdx +1 -1
  96. package/src/stories/Checkbox/Checkbox.stories.mdx +1 -1
  97. package/src/stories/CheckboxGroup/CheckboxGroup.stories.mdx +1 -1
  98. package/src/stories/CheckboxGroup/CheckboxGroupSlots.stories.mdx +1 -1
  99. package/src/stories/Combobox/Combobox.settings.ts +5 -0
  100. package/src/stories/Combobox/Combobox.stories.mdx +52 -1
  101. package/src/stories/Combobox/Combobox.test.ts +7 -0
  102. package/src/stories/Dialog/Dialog.stories.mdx +1 -1
  103. package/src/stories/Dropdown/Dropdown.settings.ts +10 -1
  104. package/src/stories/Dropdown/Dropdown.stories.mdx +18 -1
  105. package/src/stories/Icon/Icon.stories.mdx +1 -1
  106. package/src/stories/Icon/IconsCollection.stories.mdx +1 -1
  107. package/src/stories/InputText/InputText.stories.mdx +1 -1
  108. package/src/stories/Progress/Progress.stories.mdx +1 -1
  109. package/src/stories/Radio/Radio.stories.mdx +1 -1
  110. package/src/stories/RadioGroup/RadioGroup.stories.mdx +1 -1
  111. package/src/stories/RadioGroup/RadioGroupSlots.stories.mdx +1 -1
  112. package/src/stories/Select/Select.settings.ts +9 -23
  113. package/src/stories/Select/Select.stories.mdx +61 -1
  114. package/src/stories/Textarea/Textarea.stories.mdx +1 -1
  115. package/src/stories/Tooltip/Tooltip.settings.ts +26 -0
  116. package/src/stories/Tooltip/Tooltip.stories.mdx +98 -0
  117. package/src/stories/Tooltip/Tooltip.test.ts +49 -0
  118. package/src/stories/argTypes.ts +46 -22
@@ -4,8 +4,9 @@ import {
4
4
  type ExtractPropTypes,
5
5
  toRefs,
6
6
  ref,
7
+ computed,
7
8
  } from 'vue'
8
- import { DisabledProps, ModifiersProps } from '@/props'
9
+ import { DisabledProps, ModifiersProps, UnselectableProps } from '@/props'
9
10
  import type IButtonGroupState from '@/composables/group/types/IButtonGroupState'
10
11
  import { useInjectedGroupState } from '@/composables/group/useInjectedGroupState'
11
12
  import { VV_BUTTON_GROUP } from '@/constants'
@@ -42,6 +43,7 @@ export const VvButtonEvents = ['update:modelValue']
42
43
  export const VvButtonProps = {
43
44
  ...ModifiersProps,
44
45
  ...DisabledProps,
46
+ ...UnselectableProps,
45
47
  /**
46
48
  * Button icon
47
49
  */
@@ -119,7 +121,6 @@ export const VvButtonProps = {
119
121
  default: false,
120
122
  },
121
123
  modelValue: String,
122
- unselectable: { type: Boolean, default: true },
123
124
  }
124
125
 
125
126
  export type VvButtonPropsTypes = ExtractPropTypes<typeof VvButtonProps>
@@ -135,7 +136,13 @@ export function useGroupProps(
135
136
  useInjectedGroupState<IButtonGroupState>(VV_BUTTON_GROUP)
136
137
 
137
138
  // local props
138
- const { iconPosition, icon, label, pressed } = toRefs(props)
139
+ const {
140
+ iconPosition,
141
+ icon,
142
+ label,
143
+ pressed,
144
+ modifiers: localModifiers,
145
+ } = toRefs(props)
139
146
 
140
147
  // group props
141
148
  const modelValue = getGroupOrLocalRef('modelValue', props, emit) as Ref<
@@ -147,22 +154,33 @@ export function useGroupProps(
147
154
  'unselectable',
148
155
  props,
149
156
  ) as Ref<boolean>
150
- const modifiers = getGroupOrLocalRef('modifiers', props) as Ref<
151
- string[] | string
152
- >
153
157
  const multiple = group?.value?.multiple ?? ref(false)
154
158
 
159
+ const modifiers = computed(() => {
160
+ const localValue = localModifiers?.value
161
+ ? Array.isArray(localModifiers.value)
162
+ ? localModifiers.value
163
+ : [localModifiers.value]
164
+ : []
165
+ const groupValue = group?.value.itemModifiers?.value
166
+ ? Array.isArray(group.value.itemModifiers.value)
167
+ ? group.value.itemModifiers.value
168
+ : [group.value.itemModifiers.value]
169
+ : []
170
+ return [...localValue, ...groupValue]
171
+ })
172
+
155
173
  return {
156
174
  // group props
175
+ group,
176
+ isInGroup,
157
177
  modelValue,
158
178
  disabled,
159
179
  toggle,
160
- isInGroup,
161
- group,
162
- modifiers,
163
- multiple,
164
180
  unselectable,
181
+ multiple,
165
182
  // local props
183
+ modifiers,
166
184
  pressed,
167
185
  iconPosition,
168
186
  icon,
@@ -65,7 +65,7 @@
65
65
  toggle,
66
66
  multiple,
67
67
  unselectable,
68
- modifiers: itemModifiers,
68
+ itemModifiers,
69
69
  }
70
70
  useProvideGroupState(groupState)
71
71
 
@@ -1,18 +1,15 @@
1
- import { DisabledProps, ModifiersProps } from '@/props'
1
+ import { DisabledProps, ModifiersProps, UnselectableProps } from '@/props'
2
2
 
3
3
  export const VvButtonGroupProps = {
4
4
  ...ModifiersProps,
5
5
  ...DisabledProps,
6
+ ...UnselectableProps,
6
7
  /**
7
8
  * String or String[] of css classes (modifiers) that will be provided to each button'
8
9
  */
9
- itemModifiers: {
10
- type: [String, Array<string>],
11
- default: '',
12
- },
10
+ itemModifiers: { type: [String, Array<string>], default: undefined },
13
11
  toggle: { type: Boolean, default: false },
14
12
  multiple: { type: Boolean, default: false },
15
- unselectable: { type: Boolean, default: true },
16
13
  modelValue: { type: [String, Array<string>], default: undefined },
17
14
  }
18
15
 
@@ -15,6 +15,7 @@
15
15
  import { useComponentFocus } from '@/composables/useComponentFocus'
16
16
  import VvDropdown from '@/components/VvDropdown/VvDropdown.vue'
17
17
  import VvIcon from '@/components/VvIcon/VvIcon.vue'
18
+ import VvSelect from '@/components/VvSelect/VvSelect.vue'
18
19
  import HintSlotFactory from '@/components/common/HintSlot'
19
20
  import { VvComboboxProps, VvComboboxEvents } from '@/components/VvCombobox'
20
21
 
@@ -34,7 +35,7 @@
34
35
  const { focused } = useComponentFocus(dropdown, emit)
35
36
 
36
37
  // data
37
- const id = nanoid()
38
+ const hasId = computed(() => String(props.id || nanoid()))
38
39
  const searchText = ref('')
39
40
  const debouncedSearchText = refDebounced(
40
41
  searchText,
@@ -50,6 +51,7 @@
50
51
  loading,
51
52
  valid,
52
53
  invalid,
54
+ floating,
53
55
  } = toRefs(props)
54
56
 
55
57
  // emit on change search text
@@ -83,6 +85,7 @@
83
85
  invalid,
84
86
  dirty: isDirty,
85
87
  focus: focused,
88
+ floating,
86
89
  })
87
90
 
88
91
  // current options, filtered or prop options
@@ -119,7 +122,7 @@
119
122
 
120
123
  const hasLabel = computed(() => {
121
124
  return selectedOptions.value
122
- .map((option) => getOptionValue(option))
125
+ .map((option) => getOptionLabel(option))
123
126
  .join(props.separator)
124
127
  })
125
128
 
@@ -147,6 +150,7 @@
147
150
  }
148
151
 
149
152
  const dropdownProps = computed(() => ({
153
+ name: props.name,
150
154
  options: hasOptions.value,
151
155
  labelKey: props.labelKey,
152
156
  valueKey: props.valueKey,
@@ -155,17 +159,46 @@
155
159
  multiple: props.multiple,
156
160
  maxValues: props.maxValues,
157
161
  modelValue: props.modelValue,
162
+ unselectable: props.unselectable,
163
+ }))
164
+
165
+ const selectProps = computed(() => ({
166
+ id: hasId.value,
167
+ name: props.name,
168
+ tabindex: hasTabindex.value,
169
+ valid: valid.value,
170
+ validLabel: props.validLabel,
171
+ invalid: invalid.value,
172
+ invalidLabel: props.invalidLabel,
173
+ hintLabel: props.hintLabel,
174
+ loading: loading.value,
175
+ loadingLabel: props.loadingLabel,
176
+ disabled: disabled.value,
177
+ readonly: readonly.value,
178
+ modifiers: props.modifiers,
179
+ options: hasOptions.value,
180
+ labelKey: props.labelKey,
181
+ valueKey: props.valueKey,
182
+ icon: props.icon,
183
+ iconPosition: props.iconPosition,
184
+ floating: props.floating,
185
+ unselectable: props.unselectable,
186
+ multiple: props.multiple,
187
+ label: props.label,
188
+ placeholder: props.placeholder,
189
+ modelValue: props.modelValue,
158
190
  }))
159
191
  </script>
160
192
 
161
193
  <template>
162
- <div v-if="!native" :id="id" :class="bemCssClasses">
194
+ <div v-if="!native" :id="hasId" :class="bemCssClasses">
163
195
  <label
164
196
  v-if="label"
165
- :id="`${id}-label`"
166
- :for="searchable && dropdownOpen ? `${id}-input` : undefined"
167
- >{{ label }}</label
197
+ :id="`${hasId}-label`"
198
+ :for="searchable && dropdownOpen ? `${hasId}-input` : undefined"
168
199
  >
200
+ {{ label }}
201
+ </label>
169
202
  <details
170
203
  ref="dropdown"
171
204
  class="vv-select__wrapper"
@@ -189,7 +222,7 @@
189
222
  <!-- #region search input -->
190
223
  <template v-if="searchable && dropdownOpen">
191
224
  <input
192
- :id="`${id}-input`"
225
+ :id="`${hasId}-input`"
193
226
  ref="inputSearch"
194
227
  v-model="searchText"
195
228
  role="combobox"
@@ -213,15 +246,16 @@
213
246
  </summary>
214
247
  <!-- @slot Slot to replace right icon -->
215
248
  <VvDropdown
216
- :id="`${id}-dropdown`"
249
+ :id="`${hasId}-dropdown`"
217
250
  v-bind="dropdownProps"
218
251
  @update:model-value="onInput"
219
252
  />
220
253
  </details>
221
254
  <HintSlot class="vv-select__hint" />
222
255
  </div>
223
- <!-- <VvSelect
256
+ <VvSelect
224
257
  v-else
225
- v-bind="props"
226
- @update:model-value="emit('update:modelValue', $event)" /> -->
258
+ v-bind="selectProps"
259
+ @update:model-value="emit('update:modelValue', $event)"
260
+ />
227
261
  </template>
@@ -9,6 +9,9 @@ import {
9
9
  OptionsProps,
10
10
  IconProps,
11
11
  TabindexProps,
12
+ FloatingProps,
13
+ UnselectableProps,
14
+ IdNameProps,
12
15
  } from '@/props'
13
16
 
14
17
  export const VvComboboxEvents = [
@@ -19,6 +22,7 @@ export const VvComboboxEvents = [
19
22
  ]
20
23
 
21
24
  export const VvComboboxProps = {
25
+ ...IdNameProps,
22
26
  ...TabindexProps,
23
27
  ...ValidProps,
24
28
  ...InvalidProps,
@@ -29,6 +33,8 @@ export const VvComboboxProps = {
29
33
  ...ModifiersProps,
30
34
  ...OptionsProps,
31
35
  ...IconProps,
36
+ ...FloatingProps,
37
+ ...UnselectableProps,
32
38
  /**
33
39
  * modelValue can be a string, number, boolean, object or array of string, number, boolean, object
34
40
  */
@@ -5,7 +5,7 @@
5
5
  </script>
6
6
 
7
7
  <script setup lang="ts">
8
- import { toRefs } from 'vue'
8
+ import { computed, toRefs } from 'vue'
9
9
  import { nanoid } from 'nanoid'
10
10
  import { useBemModifiers } from '@/composables/useModifiers'
11
11
  import { useOptions } from '@/composables/useOptions'
@@ -18,7 +18,7 @@
18
18
  const emit = defineEmits(['update:modelValue'])
19
19
 
20
20
  // data
21
- const id = nanoid()
21
+ const hasId = computed(() => String(props.id || nanoid()))
22
22
  const { modifiers, disabled } = toRefs(props)
23
23
 
24
24
  // options
@@ -69,7 +69,7 @@
69
69
  return
70
70
  }
71
71
 
72
- let toReturn: string | string[] | Option | Option[] = value
72
+ let toReturn: string | string[] | Option | Option[] | undefined = value
73
73
  // Check multiple prop, override value with array and remove or add the value
74
74
  if (props.multiple) {
75
75
  // check maxValues prop and block check new values
@@ -90,13 +90,15 @@
90
90
  } else {
91
91
  toReturn = [value as Option]
92
92
  }
93
+ } else if (props.unselectable && value === props.modelValue) {
94
+ toReturn = undefined
93
95
  }
94
96
  emit('update:modelValue', toReturn)
95
97
  }
96
98
  </script>
97
99
 
98
100
  <template>
99
- <ul :class="dropdownClasses" role="listbox">
101
+ <ul :id="hasId" :class="dropdownClasses" role="listbox">
100
102
  <li v-if="!options?.length" role="option">
101
103
  <label>
102
104
  {{ labelNoResults }}
@@ -109,15 +111,16 @@
109
111
  :aria-selected="getChecked(option)"
110
112
  >
111
113
  <label
112
- :for="`dropdown-${index}-${id}`"
114
+ :for="`dropdown-${index}-${hasId}`"
113
115
  @click.prevent="onInput(getOptionValue(option))"
114
116
  >
115
117
  <input
116
- :id="`dropdown-${index}-${id}`"
118
+ :id="`dropdown-${index}-${hasId}`"
117
119
  :type="multiple ? 'checkbox' : 'radio'"
118
120
  :value="getOptionValue(option)"
119
121
  :checked="getChecked(option)"
120
122
  :disabled="getDisabled(option)"
123
+ :name="name"
121
124
  tabindex="-1"
122
125
  aria-hidden="true"
123
126
  />
@@ -1,6 +1,12 @@
1
- import { DisabledProps, ModifiersProps, OptionsProps } from '@/props'
1
+ import {
2
+ DisabledProps,
3
+ IdNameProps,
4
+ ModifiersProps,
5
+ OptionsProps,
6
+ } from '@/props'
2
7
 
3
8
  export const VvDropdownProps = {
9
+ ...IdNameProps,
4
10
  ...OptionsProps,
5
11
  ...DisabledProps,
6
12
  ...ModifiersProps,
@@ -22,4 +28,8 @@ export const VvDropdownProps = {
22
28
  * The max number of selected values
23
29
  */
24
30
  maxValues: [Number, String],
31
+ /**
32
+ * If true the input will be unselectable
33
+ */
34
+ unselectable: { type: Boolean, default: true },
25
35
  }
@@ -10,10 +10,11 @@
10
10
  useSlots,
11
11
  ref,
12
12
  toRefs,
13
- onMounted,
14
13
  unref,
14
+ watch,
15
15
  type InputHTMLAttributes,
16
16
  } from 'vue'
17
+ import { useElementVisibility } from '@vueuse/core'
17
18
  import { nanoid } from 'nanoid'
18
19
  import { isEmpty } from '@/utils/ObjectUtilities'
19
20
  import HintSlotFactory from '@/components/common/HintSlot'
@@ -63,6 +64,14 @@
63
64
  // focus
64
65
  const { focused } = useComponentFocus(input, emit)
65
66
 
67
+ // visibility
68
+ const isVisible = useElementVisibility(input)
69
+ watch(isVisible, (newValue) => {
70
+ if (newValue && props.autofocus) {
71
+ focused.value = true
72
+ }
73
+ })
74
+
66
75
  // password
67
76
  const showPassword = ref(false)
68
77
  const isPassword = computed(() => props.type === INPUT_TYPES.PASSWORD)
@@ -258,13 +267,6 @@
258
267
  INPUT_TYPES.SEARCH,
259
268
  props,
260
269
  )
261
-
262
- // lifecycle
263
- onMounted(() => {
264
- if (props.autofocus) {
265
- focused.value = true
266
- }
267
- })
268
270
  </script>
269
271
 
270
272
  <template>
@@ -11,6 +11,7 @@
11
11
  toRefs,
12
12
  useSlots,
13
13
  ref,
14
+ watch,
14
15
  type SelectHTMLAttributes,
15
16
  } from 'vue'
16
17
  import { nanoid } from 'nanoid'
@@ -22,6 +23,7 @@
22
23
  import VvIcon from '@/components/VvIcon/VvIcon.vue'
23
24
  import HintSlotFactory from '@/components/common/HintSlot'
24
25
  import { VvSelectProps, VvSelectEmits } from '@/components/VvSelect'
26
+ import { useElementVisibility } from '@vueuse/core'
25
27
 
26
28
  // props, emit and slots
27
29
  const props = defineProps(VvSelectProps)
@@ -44,6 +46,8 @@
44
46
  iconPosition,
45
47
  invalid,
46
48
  valid,
49
+ floating,
50
+ multiple,
47
51
  } = toRefs(props)
48
52
 
49
53
  // computed
@@ -53,6 +57,14 @@
53
57
  // focus
54
58
  const { focused } = useComponentFocus(select, emit)
55
59
 
60
+ // visibility
61
+ const isVisible = useElementVisibility(select)
62
+ watch(isVisible, (newValue) => {
63
+ if (newValue && props.autofocus) {
64
+ focused.value = true
65
+ }
66
+ })
67
+
56
68
  // icons
57
69
  const { hasIcon, hasIconLeft, hasIconRight } = useComponentIcon(
58
70
  icon,
@@ -91,6 +103,8 @@
91
103
  iconRight: hasIconRight,
92
104
  dirty: isDirty,
93
105
  focus: focused,
106
+ floating,
107
+ multiple,
94
108
  })
95
109
 
96
110
  // attrs
@@ -132,6 +146,9 @@
132
146
  return props.modelValue
133
147
  },
134
148
  set: (newValue) => {
149
+ if (Array.isArray(newValue)) {
150
+ newValue = newValue.filter((item) => item !== undefined)
151
+ }
135
152
  emit('update:modelValue', newValue)
136
153
  },
137
154
  })
@@ -151,7 +168,12 @@
151
168
  v-model="localModelValue"
152
169
  v-bind="hasAttrs"
153
170
  >
154
- <option v-if="placeholder" :value="undefined" disabled>
171
+ <option
172
+ v-if="placeholder"
173
+ :value="undefined"
174
+ :disabled="!unselectable"
175
+ :hidden="!unselectable"
176
+ >
155
177
  {{ placeholder }}
156
178
  </option>
157
179
  <option
@@ -10,10 +10,16 @@ import {
10
10
  OptionsProps,
11
11
  IconProps,
12
12
  IdNameProps,
13
+ FloatingProps,
14
+ UnselectableProps,
15
+ AutofocusProps,
16
+ AutocompleteProps,
13
17
  } from '@/props'
14
18
 
15
19
  export const VvSelectProps = {
16
20
  ...IdNameProps,
21
+ ...AutofocusProps,
22
+ ...AutocompleteProps,
17
23
  ...TabindexProps,
18
24
  ...ValidProps,
19
25
  ...InvalidProps,
@@ -24,17 +30,8 @@ export const VvSelectProps = {
24
30
  ...ModifiersProps,
25
31
  ...OptionsProps,
26
32
  ...IconProps,
27
- /**
28
- * Global attribute autocomplete
29
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-autocomplete
30
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
31
- */
32
- autocomplete: { type: String, default: 'off' },
33
- /**
34
- * Global attribute autofocus
35
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus
36
- */
37
- autofocus: Boolean,
33
+ ...FloatingProps,
34
+ ...UnselectableProps,
38
35
  /**
39
36
  * This Boolean attribute indicates that multiple options can be selected in the list.
40
37
  * If it is not specified, then only one option can be selected at a time.
@@ -5,22 +5,9 @@
5
5
  </script>
6
6
 
7
7
  <script setup lang="ts">
8
- import {
9
- computed,
10
- useSlots,
11
- ref,
12
- toRefs,
13
- onMounted,
14
- type TextareaHTMLAttributes,
15
- } from 'vue'
8
+ import type { TextareaHTMLAttributes } from 'vue'
16
9
  import { nanoid } from 'nanoid'
17
- import { isEmpty } from '@/utils/ObjectUtilities'
18
10
  import HintSlotFactory from '@/components/common/HintSlot'
19
- import { useComponentIcon } from '@/composables/useComponentIcons'
20
- import { useComponentFocus } from '@/composables/useComponentFocus'
21
- import { useDebouncedInput } from '@/composables/useDebouncedInput'
22
- import { useTextCount } from '@/composables/useTextCount'
23
- import { useBemModifiers } from '@/composables/useModifiers'
24
11
  import VvIcon from '@/components/VvIcon/VvIcon.vue'
25
12
  import { VvTextareaProps, VvTextareaEvents } from '@/components/VvTextarea'
26
13
 
@@ -62,6 +49,14 @@
62
49
  // focus
63
50
  const { focused } = useComponentFocus(textarea, emit)
64
51
 
52
+ // visibility
53
+ const isVisible = useElementVisibility(textarea)
54
+ watch(isVisible, (newValue) => {
55
+ if (newValue && props.autofocus) {
56
+ focused.value = true
57
+ }
58
+ })
59
+
65
60
  // count
66
61
  const { formatted: countFormatted } = useTextCount(localModelValue, {
67
62
  mode: props.count,
@@ -151,13 +146,6 @@
151
146
  const onClear = () => {
152
147
  localModelValue.value = undefined
153
148
  }
154
-
155
- // lifecycle
156
- onMounted(() => {
157
- if (props.autofocus) {
158
- focused.value = true
159
- }
160
- })
161
149
  </script>
162
150
 
163
151
  <template>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import { VvTooltipProps } from '@/components/VvTooltip'
3
+
4
+ const props = defineProps(VvTooltipProps)
5
+ const { modifiers } = toRefs(props)
6
+
7
+ // styles
8
+ const { bemCssClasses: tooltipClass } = useBemModifiers('vv-tooltip', {
9
+ modifiers
10
+ })
11
+ </script>
12
+
13
+ <template>
14
+ <span :class="[tooltipClass, `vv-tooltip--${props.position}`]" role="tooltip" inert>
15
+ <slot />
16
+ </span>
17
+ </template>
@@ -0,0 +1,21 @@
1
+ import { ModifiersProps } from '@/props'
2
+ import type { PropType } from 'vue'
3
+
4
+ export enum TooltipPosition {
5
+ left = 'left',
6
+ right = 'right',
7
+ top = 'top',
8
+ bottom = 'bottom'
9
+ }
10
+
11
+ export const VvTooltipProps = {
12
+ ...ModifiersProps,
13
+ /**
14
+ * Define the tooltip position
15
+ * @default TooltipPosition.bottom
16
+ */
17
+ position: {
18
+ type: String as PropType<TooltipPosition>,
19
+ default: TooltipPosition.bottom
20
+ }
21
+ }
@@ -11,5 +11,5 @@ export default interface IButtonGroupState extends IGroupState {
11
11
  toggle: Ref<boolean>
12
12
  multiple: Ref<boolean>
13
13
  unselectable: Ref<boolean>
14
- modifiers: Ref<string | Array<string> | undefined>
14
+ itemModifiers?: Ref<string | Array<string> | undefined>
15
15
  }
@@ -4,7 +4,7 @@ import type { Ref } from 'vue'
4
4
  * State shared for a group of elements
5
5
  */
6
6
  export default interface IGroupState {
7
- [itemKey: string]: Ref<unknown> | string
7
+ [itemKey: string]: Ref<unknown> | string | undefined
8
8
  // The key of the group
9
9
  key: string
10
10
  }
@@ -17,9 +17,9 @@ export function useInjectedGroupState<TGroup extends IGroupState>(
17
17
  /**
18
18
  * Get a group or local property
19
19
  */
20
- function getGroupOrLocalRef<T extends object>(
20
+ function getGroupOrLocalRef<PropsType extends object>(
21
21
  propName: keyof TGroup,
22
- props: T,
22
+ props: PropsType,
23
23
  emit?: (event: string, ...args: unknown[]) => void,
24
24
  ) {
25
25
  if (group?.value) {
@@ -33,7 +33,7 @@ export function useInjectedGroupState<TGroup extends IGroupState>(
33
33
  },
34
34
  })
35
35
  }
36
- const propRef = toRef(props, propName as keyof T)
36
+ const propRef = toRef(props, propName as keyof PropsType)
37
37
  return computed({
38
38
  get() {
39
39
  return propRef.value
@@ -33,7 +33,7 @@ export function useTextCount(
33
33
  return ''
34
34
  }
35
35
 
36
- if (options?.mode === 'limit') {
36
+ if (options?.mode === 'limit' && options?.upperLimit) {
37
37
  return `${length.value} / ${
38
38
  options.lowerLimit ? `${options.lowerLimit}-` : ''
39
39
  }${options.upperLimit}`