@volverjs/ui-vue 0.0.9 → 0.0.10-beta.10

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 (184) hide show
  1. package/README.md +64 -1
  2. package/auto-imports.d.ts +1 -1
  3. package/bin/icons.cjs +1 -1
  4. package/bin/icons.js +34 -19
  5. package/dist/components/VvAccordion/VvAccordion.es.js +33 -4
  6. package/dist/components/VvAccordion/VvAccordion.umd.js +1 -1
  7. package/dist/components/VvAccordion/VvAccordion.vue.d.ts +4 -4
  8. package/dist/components/VvAccordion/index.d.ts +1 -1
  9. package/dist/components/VvAccordionGroup/VvAccordionGroup.es.js +75 -27
  10. package/dist/components/VvAccordionGroup/VvAccordionGroup.umd.js +1 -1
  11. package/dist/components/VvAccordionGroup/VvAccordionGroup.vue.d.ts +5 -5
  12. package/dist/components/VvAction/VvAction.es.js +26 -4
  13. package/dist/components/VvAction/VvAction.umd.js +1 -1
  14. package/dist/components/VvAction/VvAction.vue.d.ts +17 -4
  15. package/dist/components/VvAction/index.d.ts +5 -0
  16. package/dist/components/VvAlert/VvAlert.es.js +96 -45
  17. package/dist/components/VvAlert/VvAlert.umd.js +1 -1
  18. package/dist/components/VvAlert/VvAlert.vue.d.ts +4 -4
  19. package/dist/components/VvAlertGroup/VvAlertGroup.es.js +136 -66
  20. package/dist/components/VvAlertGroup/VvAlertGroup.umd.js +1 -1
  21. package/dist/components/VvAlertGroup/VvAlertGroup.vue.d.ts +4 -4
  22. package/dist/components/VvAvatar/VvAvatar.es.js +22 -1
  23. package/dist/components/VvAvatar/VvAvatar.umd.js +1 -1
  24. package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +79 -28
  25. package/dist/components/VvAvatarGroup/VvAvatarGroup.umd.js +1 -1
  26. package/dist/components/VvBadge/VvBadge.es.js +39 -8
  27. package/dist/components/VvBadge/VvBadge.umd.js +1 -1
  28. package/dist/components/VvBreadcrumb/VvBreadcrumb.es.js +224 -41
  29. package/dist/components/VvBreadcrumb/VvBreadcrumb.umd.js +1 -1
  30. package/dist/components/VvBreadcrumb/VvBreadcrumb.vue.d.ts +14 -3
  31. package/dist/components/VvBreadcrumb/index.d.ts +2 -9
  32. package/dist/components/VvButton/VvButton.es.js +70 -25
  33. package/dist/components/VvButton/VvButton.umd.js +1 -1
  34. package/dist/components/VvButton/VvButton.vue.d.ts +25 -9
  35. package/dist/components/VvButton/index.d.ts +5 -0
  36. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +33 -6
  37. package/dist/components/VvButtonGroup/VvButtonGroup.umd.js +1 -1
  38. package/dist/components/VvButtonGroup/VvButtonGroup.vue.d.ts +6 -6
  39. package/dist/components/VvCard/VvCard.es.js +47 -16
  40. package/dist/components/VvCard/VvCard.umd.js +1 -1
  41. package/dist/components/VvCheckbox/VvCheckbox.es.js +35 -7
  42. package/dist/components/VvCheckbox/VvCheckbox.umd.js +1 -1
  43. package/dist/components/VvCheckbox/VvCheckbox.vue.d.ts +8 -8
  44. package/dist/components/VvCheckbox/index.d.ts +1 -1
  45. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.es.js +106 -51
  46. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.umd.js +1 -1
  47. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.vue.d.ts +7 -7
  48. package/dist/components/VvCheckboxGroup/index.d.ts +1 -1
  49. package/dist/components/VvCombobox/VvCombobox.es.js +635 -400
  50. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  51. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +112 -112
  52. package/dist/components/VvCombobox/index.d.ts +32 -32
  53. package/dist/components/VvDialog/VvDialog.es.js +65 -27
  54. package/dist/components/VvDialog/VvDialog.umd.js +1 -1
  55. package/dist/components/VvDialog/VvDialog.vue.d.ts +4 -4
  56. package/dist/components/VvDropdown/VvDropdown.es.js +87 -46
  57. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  58. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +203 -189
  59. package/dist/components/VvDropdown/VvDropdownAction.vue.d.ts +12 -0
  60. package/dist/components/VvDropdown/index.d.ts +32 -32
  61. package/dist/components/VvDropdownAction/VvDropdownAction.es.js +46 -12
  62. package/dist/components/VvDropdownAction/VvDropdownAction.umd.js +1 -1
  63. package/dist/components/VvDropdownItem/VvDropdownItem.es.js +13 -7
  64. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.es.js +28 -1
  65. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.umd.js +1 -1
  66. package/dist/components/VvDropdownOption/VvDropdownOption.es.js +40 -8
  67. package/dist/components/VvDropdownOption/VvDropdownOption.umd.js +1 -1
  68. package/dist/components/VvIcon/VvIcon.es.js +1 -1
  69. package/dist/components/VvIcon/VvIcon.umd.js +1 -1
  70. package/dist/components/VvInputText/VvInputClearAction.d.ts +1 -1
  71. package/dist/components/VvInputText/VvInputText.es.js +149 -99
  72. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  73. package/dist/components/VvInputText/VvInputText.vue.d.ts +10 -10
  74. package/dist/components/VvInputText/index.d.ts +8 -2
  75. package/dist/components/VvNav/VvNav.es.js +115 -63
  76. package/dist/components/VvNav/VvNav.umd.js +1 -1
  77. package/dist/components/VvNav/VvNav.vue.d.ts +31 -12
  78. package/dist/components/VvNav/VvNavItem.vue.d.ts +9 -0
  79. package/dist/components/VvNav/index.d.ts +1 -12
  80. package/dist/components/VvNavItem/VvNavItem.es.js +413 -0
  81. package/dist/components/VvNavItem/VvNavItem.umd.js +1 -0
  82. package/dist/components/VvNavSeparator/VvNavSeparator.es.js +24 -0
  83. package/dist/components/VvNavSeparator/VvNavSeparator.umd.js +1 -0
  84. package/dist/components/VvProgress/VvProgress.es.js +33 -6
  85. package/dist/components/VvProgress/VvProgress.umd.js +1 -1
  86. package/dist/components/VvRadio/VvRadio.es.js +35 -7
  87. package/dist/components/VvRadio/VvRadio.umd.js +1 -1
  88. package/dist/components/VvRadio/VvRadio.vue.d.ts +8 -8
  89. package/dist/components/VvRadio/index.d.ts +1 -1
  90. package/dist/components/VvRadioGroup/VvRadioGroup.es.js +106 -51
  91. package/dist/components/VvRadioGroup/VvRadioGroup.umd.js +1 -1
  92. package/dist/components/VvRadioGroup/VvRadioGroup.vue.d.ts +7 -7
  93. package/dist/components/VvRadioGroup/index.d.ts +1 -1
  94. package/dist/components/VvSelect/VvSelect.es.js +159 -99
  95. package/dist/components/VvSelect/VvSelect.umd.js +1 -1
  96. package/dist/components/VvSelect/VvSelect.vue.d.ts +13 -13
  97. package/dist/components/VvSelect/index.d.ts +1 -1
  98. package/dist/components/VvTab/VvTab.es.js +214 -99
  99. package/dist/components/VvTab/VvTab.umd.js +1 -1
  100. package/dist/components/VvTab/VvTab.vue.d.ts +40 -11
  101. package/dist/components/VvTab/index.d.ts +9 -3
  102. package/dist/components/VvTextarea/VvTextarea.es.js +123 -77
  103. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  104. package/dist/components/VvTextarea/VvTextarea.vue.d.ts +10 -10
  105. package/dist/components/VvTooltip/VvTooltip.es.js +40 -9
  106. package/dist/components/VvTooltip/VvTooltip.umd.js +1 -1
  107. package/dist/components/index.es.js +1593 -1012
  108. package/dist/components/index.umd.js +1 -1
  109. package/dist/composables/group/useInjectedGroupState.d.ts +1 -1
  110. package/dist/composables/useOptions.d.ts +1 -1
  111. package/dist/composables/useVolver.d.ts +1 -1
  112. package/dist/directives/index.d.ts +3 -5
  113. package/dist/directives/index.es.js +60 -23
  114. package/dist/directives/index.umd.js +1 -1
  115. package/dist/directives/v-tooltip.es.js +58 -18
  116. package/dist/directives/v-tooltip.umd.js +1 -1
  117. package/dist/icons.es.js +3 -3
  118. package/dist/icons.umd.js +1 -1
  119. package/dist/index.d.ts +3 -1
  120. package/dist/index.es.js +19 -16
  121. package/dist/index.umd.js +1 -1
  122. package/dist/props/index.d.ts +58 -34
  123. package/dist/stories/AccordionGroup/AccordionGroup.stories.d.ts +50 -15
  124. package/dist/stories/AccordionGroup/AccordionGroupSlots.stories.d.ts +332 -83
  125. package/dist/stories/Combobox/Combobox.settings.d.ts +8 -0
  126. package/dist/stories/Combobox/ComboboxOptions.stories.d.ts +1 -0
  127. package/dist/stories/InputText/InputTextMask.stories.d.ts +1 -1
  128. package/dist/stories/Tab/Tab.settings.d.ts +4 -37
  129. package/dist/types/alert.d.ts +13 -0
  130. package/dist/types/floating-ui.d.ts +6 -0
  131. package/dist/types/generic.d.ts +4 -0
  132. package/dist/types/group.d.ts +37 -0
  133. package/dist/types/index.d.ts +5 -0
  134. package/dist/types/nav.d.ts +17 -0
  135. package/package.json +61 -52
  136. package/src/Volver.ts +22 -16
  137. package/src/assets/icons/detailed.json +1 -1
  138. package/src/assets/icons/normal.json +1 -1
  139. package/src/assets/icons/simple.json +1 -1
  140. package/src/components/VvAccordion/VvAccordion.vue +2 -2
  141. package/src/components/VvAction/VvAction.vue +5 -2
  142. package/src/components/VvBreadcrumb/VvBreadcrumb.vue +20 -19
  143. package/src/components/VvBreadcrumb/index.ts +2 -8
  144. package/src/components/VvCombobox/VvCombobox.vue +32 -33
  145. package/src/components/VvCombobox/index.ts +4 -0
  146. package/src/components/VvInputText/VvInputText.vue +2 -2
  147. package/src/components/VvNav/VvNav.vue +30 -50
  148. package/src/components/VvNav/VvNavItem.vue +18 -0
  149. package/src/components/VvNav/VvNavSeparator.vue +11 -0
  150. package/src/components/VvNav/index.ts +2 -15
  151. package/src/components/VvSelect/VvSelect.vue +4 -4
  152. package/src/components/VvTab/VvTab.vue +63 -35
  153. package/src/components/VvTab/index.ts +10 -4
  154. package/src/components/VvTextarea/VvTextarea.vue +1 -1
  155. package/src/composables/useOptions.ts +2 -2
  156. package/src/composables/useUniqueId.ts +2 -2
  157. package/src/directives/index.ts +1 -4
  158. package/src/directives/v-tooltip.ts +19 -10
  159. package/src/index.ts +3 -1
  160. package/src/props/index.ts +27 -3
  161. package/src/stories/Button/ButtonModifiers.stories.ts +4 -14
  162. package/src/stories/Combobox/Combobox.settings.ts +8 -0
  163. package/src/stories/Combobox/ComboboxOptions.stories.ts +18 -0
  164. package/src/stories/InputText/InputTextMask.stories.ts +1 -1
  165. package/src/stories/Nav/Nav.settings.ts +3 -4
  166. package/src/stories/Nav/Nav.test.ts +4 -15
  167. package/src/stories/Tab/Tab.settings.ts +9 -9
  168. package/src/stories/Tab/Tab.stories.ts +2 -2
  169. package/src/stories/Tab/Tab.test.ts +6 -14
  170. package/src/stories/argTypes.ts +1 -1
  171. package/src/types/generic.ts +6 -0
  172. package/src/types/index.ts +5 -0
  173. package/src/types/nav.ts +19 -0
  174. package/src/utils/ObjectUtilities.ts +3 -2
  175. package/dist/components/VvNav/VvNavItemTitle.vue.d.ts +0 -6
  176. package/dist/components/VvNavItemTitle/VvNavItemTitle.es.js +0 -19
  177. package/dist/components/VvNavItemTitle/VvNavItemTitle.umd.js +0 -1
  178. package/src/components/VvNav/VvNavItemTitle.vue +0 -11
  179. package/src/components/VvNav/VvNavSeparator.ts +0 -8
  180. package/src/types/generic.d.ts +0 -6
  181. /package/dist/components/VvNav/{VvNavSeparator.d.ts → VvNavSeparator.vue.d.ts} +0 -0
  182. /package/src/types/{alert.d.ts → alert.ts} +0 -0
  183. /package/src/types/{floating-ui.d.ts → floating-ui.ts} +0 -0
  184. /package/src/types/{group.d.ts → group.ts} +0 -0
@@ -5,7 +5,7 @@
5
5
  </script>
6
6
 
7
7
  <script setup lang="ts">
8
- import { nanoid } from 'nanoid'
8
+ import { uid } from 'uid'
9
9
  import { VvAccordionEvents, VvAccordionProps, useGroupProps } from '.'
10
10
 
11
11
  // props, attrs and emit
@@ -15,7 +15,7 @@
15
15
 
16
16
  // data
17
17
  const accordionName = computed(
18
- () => props.name || (attrs?.id as string) || nanoid(),
18
+ () => props.name || (attrs?.id as string) || uid(),
19
19
  )
20
20
  const {
21
21
  modifiers,
@@ -55,7 +55,7 @@
55
55
  case props.href !== undefined:
56
56
  return ActionTag.a
57
57
  default:
58
- return ActionTag.button
58
+ return props.defaultTag // button
59
59
  }
60
60
  })
61
61
 
@@ -85,12 +85,14 @@
85
85
  to: props.to,
86
86
  target: props.target,
87
87
  }
88
- default:
88
+ case ActionTag.button:
89
89
  return {
90
90
  ...toReturn,
91
91
  type: props.type,
92
92
  disabled: props.disabled,
93
93
  }
94
+ default:
95
+ return toReturn
94
96
  }
95
97
  })
96
98
 
@@ -132,6 +134,7 @@
132
134
  active,
133
135
  pressed,
134
136
  disabled,
137
+ current,
135
138
  }"
136
139
  @click.passive="onClick"
137
140
  @mouseover.passive="onMouseover"
@@ -7,46 +7,47 @@
7
7
  <script setup lang="ts">
8
8
  import { useModifiers } from '../../composables/useModifiers'
9
9
  import { VvBreadcrumbProps } from '.'
10
+ import VvAction from '../VvAction/VvAction.vue'
10
11
 
11
12
  const props = defineProps(VvBreadcrumbProps)
12
13
  const { modifiers } = toRefs(props)
13
14
  const bemCssClasses = useModifiers('vv-breadcrumb', modifiers)
15
+ const length = computed(() => props.routes?.length ?? 0)
16
+
17
+ const isLast = (index: number) => index === length.value - 1
14
18
  </script>
15
19
 
16
20
  <template>
17
21
  <nav :class="bemCssClasses" aria-label="breadcrumbs">
18
22
  <ol class="vv-breadcrumb__list">
19
23
  <li
20
- v-for="(route, index) in routes"
21
- :key="`${route.label}-${index}`"
22
- :class="{
23
- 'vv-breadcrumb__item': index < Number(routes?.length) - 1,
24
- 'vv-breadcrumb__item-active':
25
- index === Number(routes?.length) - 1,
26
- }"
24
+ v-for="({ label, ...route }, index) in routes"
25
+ :key="`${label}-${index}`"
26
+ :class="
27
+ !isLast(index)
28
+ ? 'vv-breadcrumb__item'
29
+ : 'vv-breadcrumb__item-active'
30
+ "
27
31
  itemprop="itemListElement"
28
32
  itemtype="https://schema.org/ListItem"
29
33
  itemscope
30
34
  >
31
- <Component
32
- :is="route.to ? 'router-link' : route.href ? 'a' : 'span'"
35
+ <VvAction
33
36
  v-bind="route"
34
- :class="{
35
- 'vv-breadcrumb__link':
36
- index < Number(routes?.length) - 1,
37
- }"
38
- :aria-current="
39
- index === Number(routes?.length) - 1
40
- ? 'page'
41
- : undefined
37
+ :class="
38
+ !isLast(index)
39
+ ? 'vv-breadcrumb__link'
40
+ : 'vv-breadcrumb__label'
42
41
  "
42
+ :aria-current="isLast(index) ? 'page' : undefined"
43
43
  itemprop="item"
44
+ default-tag="span"
44
45
  >
45
46
  <!-- @slot Slot for label -->
46
47
  <slot name="label" v-bind="{ route, index }">
47
- {{ route.label }}
48
+ {{ label }}
48
49
  </slot>
49
- </Component>
50
+ </VvAction>
50
51
  <meta itemprop="position" :content="`${index + 1}`" />
51
52
  </li>
52
53
  </ol>
@@ -1,13 +1,7 @@
1
1
  import { ModifiersProps } from '../../props'
2
-
3
- export interface Route {
4
- label: string
5
- to?: string | { [key: string]: unknown }
6
- title?: string
7
- href?: string
8
- }
2
+ import type { NavItem } from '../../types'
9
3
 
10
4
  export const VvBreadcrumbProps = {
11
5
  ...ModifiersProps,
12
- routes: Array as PropType<Route[]>,
6
+ routes: Array as PropType<NavItem[]>,
13
7
  }
@@ -87,9 +87,13 @@
87
87
  searchText,
88
88
  computed(() => Number(props.debounceSearch)),
89
89
  )
90
- watch(debouncedSearchText, () =>
91
- emit('change:search', debouncedSearchText.value),
92
- )
90
+ watch(debouncedSearchText, () => {
91
+ emit('update:search', debouncedSearchText.value)
92
+ /**
93
+ * @deprecated change:search should not be used, use update:search instead
94
+ */
95
+ emit('change:search', debouncedSearchText.value)
96
+ })
93
97
 
94
98
  // expanded
95
99
  const expanded = ref(false)
@@ -173,7 +177,7 @@
173
177
  valid: valid.value,
174
178
  invalid: invalid.value,
175
179
  dirty: isDirty.value,
176
- focus: focused.value,
180
+ focus: focused.value || focusedWithin.value || expanded.value,
177
181
  floating: floating.value,
178
182
  badges: props.badges,
179
183
  })),
@@ -182,8 +186,8 @@
182
186
  const {
183
187
  getOptionLabel,
184
188
  getOptionValue,
185
- getOptionDisabled,
186
189
  getOptionGrouped,
190
+ isOptionDisabled,
187
191
  } = useOptions(props)
188
192
 
189
193
  // options filtered by search text
@@ -210,7 +214,7 @@
210
214
  * Check if an option exist into modelValue array (multiple) or is equal to modelValue (single)
211
215
  * @param {String | Option} option
212
216
  */
213
- function getOptionSelected(option: string | Option) {
217
+ function isOptionSelected(option: string | Option) {
214
218
  if (Array.isArray(props.modelValue)) {
215
219
  // check if contain whole option or option value
216
220
  return (
@@ -230,29 +234,17 @@
230
234
  * Check if is multiple mode, object mode or "string" mode
231
235
  */
232
236
  const selectedOptions = computed(() => {
233
- let selectedValues: Array<typeof props.modelValue> = []
234
- if (Array.isArray(props.modelValue)) {
235
- selectedValues = props.modelValue as Array<typeof props.modelValue>
236
- } else if (props.modelValue) {
237
- selectedValues = [props.modelValue]
238
- }
239
- const options = props.options.reduce(
237
+ const options = props.options.reduce<Array<Option | string>>(
240
238
  (acc, value) => {
241
239
  if (isGroup(value)) {
242
240
  return [...acc, ...getOptionGrouped(value)]
243
241
  }
244
242
  return [...acc, value]
245
243
  },
246
- [] as Array<Option | string>,
244
+ [],
247
245
  )
248
-
249
246
  return options.filter((option) => {
250
- if (isGroup(option)) {
251
- return getOptionGrouped(option).some((item) =>
252
- selectedValues.includes(getOptionValue(item)),
253
- )
254
- }
255
- return selectedValues.includes(getOptionValue(option))
247
+ return isOptionSelected(option)
256
248
  })
257
249
  })
258
250
 
@@ -278,12 +270,13 @@
278
270
  return
279
271
  }
280
272
 
273
+ // get option value
281
274
  const value = getOptionValue(option)
282
-
283
275
  let toReturn: string | string[] | Option | Option[] | undefined = value
284
- // Check multiple prop, override value with array and remove or add the value
276
+
277
+ // check multiple prop, override value with array and remove or add the value
285
278
  if (props.multiple) {
286
- // check maxValues prop and block check new values
279
+ // check max-values prop and block check new values
287
280
  if (Array.isArray(props.modelValue)) {
288
281
  const maxValues = Number(props.maxValues)
289
282
  if (
@@ -306,7 +299,13 @@
306
299
  if (!props.keepOpen) {
307
300
  collapse()
308
301
  }
309
- if (props.unselectable && value === props.modelValue) {
302
+ if (Array.isArray(props.modelValue)) {
303
+ if (props.unselectable && props.modelValue.includes(value)) {
304
+ toReturn = []
305
+ } else {
306
+ toReturn = [value]
307
+ }
308
+ } else if (props.unselectable && value === props.modelValue) {
310
309
  toReturn = undefined
311
310
  }
312
311
  }
@@ -518,8 +517,8 @@
518
517
  option,
519
518
  )"
520
519
  v-bind="{
521
- disabled: getOptionDisabled(item),
522
- selected: getOptionSelected(item),
520
+ selected: isOptionSelected(item),
521
+ disabled: isOptionDisabled(item),
523
522
  unselectable,
524
523
  deselectHintLabel:
525
524
  propsDefaults.deselectHintLabel,
@@ -538,8 +537,8 @@
538
537
  v-bind="{
539
538
  option,
540
539
  selectedOptions,
541
- selected: getOptionSelected(item),
542
- disabled: getOptionDisabled(item),
540
+ selected: isOptionSelected(item),
541
+ disabled: isOptionDisabled(item),
543
542
  }"
544
543
  >
545
544
  {{ getOptionLabel(item) }}
@@ -549,8 +548,8 @@
549
548
  <VvDropdownOption
550
549
  v-else
551
550
  v-bind="{
552
- disabled: getOptionDisabled(option),
553
- selected: getOptionSelected(option),
551
+ selected: isOptionSelected(option),
552
+ disabled: isOptionDisabled(option),
554
553
  unselectable,
555
554
  deselectHintLabel:
556
555
  propsDefaults.deselectHintLabel,
@@ -568,8 +567,8 @@
568
567
  v-bind="{
569
568
  option,
570
569
  selectedOptions,
571
- selected: getOptionSelected(option),
572
- disabled: getOptionDisabled(option),
570
+ selected: isOptionSelected(option),
571
+ disabled: isOptionDisabled(option),
573
572
  }"
574
573
  >
575
574
  {{ getOptionLabel(option) }}
@@ -20,6 +20,10 @@ import type { Option } from '../../types/generic'
20
20
 
21
21
  export const VvComboboxEvents = [
22
22
  'update:modelValue',
23
+ 'update:search',
24
+ /**
25
+ * @deprecated change:search should not be used, use update:search instead
26
+ */
23
27
  'change:search',
24
28
  'focus',
25
29
  'blur',
@@ -227,7 +227,7 @@
227
227
  return
228
228
  }
229
229
  inputEl.value.stepUp()
230
- localModelValue.value = unref(inputEl).value
230
+ localModelValue.value = Number(unref(inputEl).value)
231
231
  }
232
232
  }
233
233
  const onStepDown = () => {
@@ -238,7 +238,7 @@
238
238
  return
239
239
  }
240
240
  inputEl.value.stepDown()
241
- localModelValue.value = unref(inputEl).value
241
+ localModelValue.value = Number(unref(inputEl).value)
242
242
  }
243
243
  }
244
244
 
@@ -1,66 +1,46 @@
1
1
  <script setup lang="ts">
2
- import { VvNavProps, VvNavEvents, type NavItem } from '@/components/VvNav'
3
- import VvAction from '@/components/VvAction/VvAction.vue'
2
+ import { VvNavProps, VvNavEvents } from '@/components/VvNav'
3
+ import VvNavItem from './VvNavItem.vue'
4
4
 
5
5
  const props = defineProps(VvNavProps)
6
- const emit = defineEmits(VvNavEvents)
7
- const { modifiers, items } = toRefs(props)
8
- const activeItem: Ref<string | null> = ref(null)
6
+ const { modifiers } = toRefs(props)
9
7
 
10
- // bem css classes
11
- const bemCssClasses = useModifiers('vv-nav', modifiers)
12
-
13
- const localItems = computed(() => {
14
- return items.value.map((item, index) => {
15
- return {
16
- ...item,
17
- id: item.id || `nav-item_${index}`,
8
+ const emit = defineEmits(VvNavEvents)
9
+ const onClick = (event: Event) => {
10
+ const target = event.target as HTMLElement
11
+ if (target?.dataset.index) {
12
+ const index = parseInt(target.dataset.index)
13
+ const item = props.items?.[index]
14
+ if (!item || item?.disabled) {
15
+ return
18
16
  }
19
- })
20
- })
21
-
22
- /**
23
- * Triggers when the item is clicked.
24
- * @private
25
- * @event click
26
- * @param [NavItem, string] item - the clicked item
27
- */
28
- function onClick(item: NavItem) {
29
- if (!item.disabled) {
30
17
  emit('click', item)
31
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
32
- activeItem.value = item.id!
33
18
  }
34
19
  }
20
+
21
+ // bem css classes
22
+ const bemCssClasses = useModifiers('vv-nav', modifiers)
35
23
  </script>
36
24
 
37
25
  <template>
38
26
  <nav :class="bemCssClasses">
39
- <ul class="vv-nav__menu" role="menu" aria-busy="true">
40
- <li
41
- v-for="navItem in localItems"
42
- :key="navItem.id"
43
- class="vv-nav__item"
44
- role="presentation"
45
- >
46
- <VvAction
47
- v-bind="{
48
- disabled: navItem.disabled,
49
- to: navItem.to,
50
- href: navItem.href,
51
- tabindex: 0,
52
- }"
53
- :class="{
54
- current: activeItem == navItem.id,
55
- disabled: navItem.disabled,
56
- }"
57
- class="vv-nav__item-label"
58
- v-on="navItem.on"
59
- @click="onClick(navItem)"
27
+ <ul
28
+ class="vv-nav__menu"
29
+ role="menu"
30
+ aria-busy="true"
31
+ @click.stop="onClick"
32
+ >
33
+ <slot>
34
+ <VvNavItem
35
+ v-for="({ on = {}, ...item }, index) in items"
36
+ :key="index"
37
+ :data-index="index"
38
+ v-bind="item"
39
+ v-on="on"
60
40
  >
61
- {{ navItem.title }}
62
- </VvAction>
63
- </li>
41
+ <slot name="item" v-bind="{ item, index }" />
42
+ </VvNavItem>
43
+ </slot>
64
44
  </ul>
65
45
  </nav>
66
46
  </template>
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'VvNavItem',
4
+ inheritAttrs: false,
5
+ }
6
+ </script>
7
+
8
+ <script setup lang="ts">
9
+ import VvAction from '@/components/VvAction/VvAction.vue'
10
+ </script>
11
+
12
+ <template>
13
+ <li class="vv-nav__item" role="presentation">
14
+ <VvAction v-bind="$attrs" class="vv-nav__item-label">
15
+ <slot />
16
+ </VvAction>
17
+ </li>
18
+ </template>
@@ -0,0 +1,11 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'VvNavSeparator',
4
+ }
5
+ </script>
6
+
7
+ <template>
8
+ <li class="vv-nav__separator" role="separator">
9
+ <slot />
10
+ </li>
11
+ </template>
@@ -1,21 +1,8 @@
1
- import { ModifiersProps } from '@/props'
2
-
3
- export type NavItem = {
4
- id?: string
5
- title: string
6
- to?: string | { [key: string]: unknown }
7
- href?: string
8
- disabled?: boolean
9
- on?: Record<string, () => void>
10
- }
1
+ import { ModifiersProps, NavProps } from '@/props'
11
2
 
12
3
  export const VvNavProps = {
13
4
  ...ModifiersProps,
14
- items: {
15
- type: Array as PropType<NavItem[]>,
16
- required: true,
17
- default: () => [],
18
- },
5
+ ...NavProps,
19
6
  }
20
7
 
21
8
  export const VvNavEvents = ['click']
@@ -139,7 +139,7 @@
139
139
  const {
140
140
  getOptionLabel,
141
141
  getOptionValue,
142
- getOptionDisabled,
142
+ isOptionDisabled,
143
143
  getOptionGrouped,
144
144
  } = useOptions(props)
145
145
 
@@ -195,7 +195,7 @@
195
195
  <option
196
196
  v-if="!isGroup(option)"
197
197
  :key="index"
198
- :disabled="getOptionDisabled(option)"
198
+ :disabled="isOptionDisabled(option)"
199
199
  :value="getOptionValue(option)"
200
200
  >
201
201
  {{ getOptionLabel(option) }}
@@ -203,13 +203,13 @@
203
203
  <optgroup
204
204
  v-else
205
205
  :key="`group-${index}`"
206
- :disabled="getOptionDisabled(option)"
206
+ :disabled="isOptionDisabled(option)"
207
207
  :label="getOptionLabel(option)"
208
208
  >
209
209
  <option
210
210
  v-for="(item, i) in getOptionGrouped(option)"
211
211
  :key="`group-${index}-item-${i}`"
212
- :disabled="getOptionDisabled(item)"
212
+ :disabled="isOptionDisabled(item)"
213
213
  :value="getOptionValue(item)"
214
214
  >
215
215
  {{ getOptionLabel(item) }}
@@ -1,53 +1,81 @@
1
1
  <script setup lang="ts">
2
2
  import { VvTabProps, VvTabEvents } from '@/components/VvTab'
3
- import type { NavItem } from '@/components/VvNav'
4
3
  import VvNav from '@/components/VvNav/VvNav.vue'
4
+ import type { NavItemTab } from '@/types/nav'
5
5
 
6
6
  const props = defineProps(VvTabProps)
7
7
  const emit = defineEmits(VvTabEvents)
8
8
  const { modifiers, items } = toRefs(props)
9
- const activeTab: Ref<string | null> = ref(null)
10
-
11
- // bem css classes
12
- const bemCssClasses = useModifiers('vv-tab', modifiers)
13
-
14
- const localItems = computed(() => {
15
- return items.value.map((item, index) => {
16
- return {
17
- ...item,
18
- id: item.id || `tab-item_${index}`,
9
+ const tabKeys = computed(() => {
10
+ return items.value.reduce<string[]>((acc, item) => {
11
+ if (item.tab) {
12
+ acc.push(item.tab)
19
13
  }
20
- })
14
+ return acc
15
+ }, [])
21
16
  })
22
-
23
- /**
24
- * Triggers when the item is clicked.
25
- * @private
26
- * @event click
27
- * @param [NavItem, string] item - the clicked item
28
- */
29
- function onClick(item: NavItem) {
30
- if (!item.disabled) {
31
- emit('click', item)
32
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
33
- activeTab.value = item.id!
17
+ const localModelValue = ref<string | undefined>()
18
+ const activeTabKey = computed({
19
+ get: () => {
20
+ return (
21
+ props.modelValue || localModelValue.value || tabKeys.value?.[0]
22
+ )
23
+ },
24
+ set: (newValue) => {
25
+ localModelValue.value = newValue
26
+ emit('update:modelValue', newValue)
27
+ },
28
+ })
29
+ const hasNavModifiers = computed(() => {
30
+ return [
31
+ 'tabs',
32
+ ...(Array.isArray(props.navModifiers)
33
+ ? props.navModifiers
34
+ : props.navModifiers?.split(' ') ?? []),
35
+ ]
36
+ })
37
+ const onNavClick = (item: NavItemTab) => {
38
+ if (item.tab) {
39
+ activeTabKey.value = item.tab
34
40
  }
35
41
  }
42
+ const navItems = computed(() =>
43
+ props.items.map((item) => ({
44
+ current: item.tab === activeTabKey.value,
45
+ ...item,
46
+ })),
47
+ )
48
+
49
+ // bem css classes
50
+ const bemCssClasses = useModifiers('vv-tab', modifiers)
36
51
  </script>
37
52
 
38
53
  <template>
39
54
  <div :class="bemCssClasses">
40
- <VvNav :items="localItems" modifiers="tabs full" @click="onClick" />
41
- <!-- #region tab content -->
42
- <article
43
- v-for="item in localItems"
44
- :id="item.id"
45
- :key="item.id"
46
- :class="{ target: activeTab === item.id }"
47
- class="vv-tab__panel"
55
+ <!-- #region nav -->
56
+ <VvNav
57
+ v-bind="{
58
+ items: navItems,
59
+ modifiers: hasNavModifiers,
60
+ }"
61
+ @click="onNavClick"
48
62
  >
49
- <slot :name="`${item.id}`" />
50
- </article>
51
- <!-- #endregion tab content -->
63
+ <template #item="{ item, index }">
64
+ <slot name="nav-item" v-bind="{ item, index }" />
65
+ </template>
66
+ </VvNav>
67
+ <!-- #endregion -->
68
+
69
+ <!-- #region panels -->
70
+ <template v-for="(item, index) in items" :key="index">
71
+ <article
72
+ v-if="item.tab"
73
+ :class="{ target: activeTabKey === item.tab }"
74
+ class="vv-tab__panel"
75
+ >
76
+ <slot :name="`panel::${item.tab}`" />
77
+ </article>
78
+ </template>
79
+ <!-- #endregion -->
52
80
  </div>
53
81
  </template>
@@ -1,13 +1,19 @@
1
1
  import { ModifiersProps } from '@/props'
2
- import type { NavItem } from '../VvNav'
2
+ import type { NavItemTab } from '@/types/nav'
3
3
 
4
4
  export const VvTabProps = {
5
5
  ...ModifiersProps,
6
+ navModifiers: {
7
+ type: [String, Array] as PropType<string | string[]>,
8
+ },
9
+ modelValue: {
10
+ type: String,
11
+ default: '',
12
+ },
6
13
  items: {
7
- type: Array as PropType<NavItem[]>,
8
- required: true,
14
+ type: Array as PropType<NavItemTab[]>,
9
15
  default: () => [],
10
16
  },
11
17
  }
12
18
 
13
- export const VvTabEvents = ['click']
19
+ export const VvTabEvents = ['update:modelValue']
@@ -117,7 +117,7 @@
117
117
  'icon-after': hasIconAfter.value,
118
118
  floating: props.floating && !isEmpty(props.label),
119
119
  dirty: isDirty.value,
120
- focused: focused.value,
120
+ focus: focused.value,
121
121
  resizable: props.resizable,
122
122
  })),
123
123
  )
@@ -24,7 +24,7 @@ export function useOptions(props: any) {
24
24
  : get(option, valueKey.value)
25
25
  }
26
26
 
27
- const getOptionDisabled = (option: string | Option): boolean => {
27
+ const isOptionDisabled = (option: string | Option): boolean => {
28
28
  if (typeof option !== 'object' && option !== null) return false
29
29
 
30
30
  return typeof disabledKey.value === 'function'
@@ -41,7 +41,7 @@ export function useOptions(props: any) {
41
41
  options,
42
42
  getOptionLabel,
43
43
  getOptionValue,
44
- getOptionDisabled,
44
+ isOptionDisabled,
45
45
  getOptionGrouped,
46
46
  }
47
47
  }