@volverjs/ui-vue 0.0.9-beta.2 → 0.0.9-beta.21

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 (146) hide show
  1. package/README.md +3 -3
  2. package/auto-imports.d.ts +2 -0
  3. package/dist/components/VvAccordion/VvAccordion.es.js +15 -7
  4. package/dist/components/VvAccordionGroup/VvAccordionGroup.es.js +15 -7
  5. package/dist/components/VvAction/VvAction.es.js +17 -8
  6. package/dist/components/VvAction/VvAction.umd.js +1 -1
  7. package/dist/components/VvAction/VvAction.vue.d.ts +9 -0
  8. package/dist/components/VvAction/index.d.ts +4 -0
  9. package/dist/components/VvAlert/VvAlert.es.js +22 -13
  10. package/dist/components/VvAlert/VvAlert.umd.js +1 -1
  11. package/dist/components/VvAlert/VvAlert.vue.d.ts +6 -6
  12. package/dist/components/VvAlert/index.d.ts +3 -3
  13. package/dist/components/VvAlertGroup/VvAlertGroup.es.js +22 -13
  14. package/dist/components/VvAlertGroup/VvAlertGroup.umd.js +1 -1
  15. package/dist/components/VvAlertGroup/VvAlertGroup.vue.d.ts +6 -6
  16. package/dist/components/VvAlertGroup/index.d.ts +2 -2
  17. package/dist/components/VvAvatar/VvAvatar.es.js +15 -7
  18. package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +15 -7
  19. package/dist/components/VvBadge/VvBadge.es.js +15 -7
  20. package/dist/components/VvBreadcrumb/VvBreadcrumb.es.js +15 -7
  21. package/dist/components/VvButton/VvButton.es.js +19 -9
  22. package/dist/components/VvButton/VvButton.umd.js +1 -1
  23. package/dist/components/VvButton/VvButton.vue.d.ts +9 -0
  24. package/dist/components/VvButton/index.d.ts +4 -0
  25. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +15 -7
  26. package/dist/components/VvCard/VvCard.es.js +15 -7
  27. package/dist/components/VvCheckbox/VvCheckbox.es.js +99 -21
  28. package/dist/components/VvCheckbox/VvCheckbox.umd.js +1 -1
  29. package/dist/components/VvCheckbox/VvCheckbox.vue.d.ts +4 -4
  30. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.es.js +105 -22
  31. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.umd.js +1 -1
  32. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.vue.d.ts +4 -4
  33. package/dist/components/VvCombobox/VvCombobox.es.js +256 -191
  34. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  35. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +329 -101
  36. package/dist/components/VvCombobox/index.d.ts +123 -37
  37. package/dist/components/VvDialog/VvDialog.es.js +50 -37
  38. package/dist/components/VvDialog/VvDialog.umd.js +1 -1
  39. package/dist/components/VvDropdown/VvDropdown.es.js +32 -18
  40. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  41. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +300 -92
  42. package/dist/components/VvDropdown/VvDropdownAction.vue.d.ts +9 -0
  43. package/dist/components/VvDropdown/index.d.ts +99 -30
  44. package/dist/components/VvDropdownAction/VvDropdownAction.es.js +17 -8
  45. package/dist/components/VvDropdownAction/VvDropdownAction.umd.js +1 -1
  46. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.es.js +15 -7
  47. package/dist/components/VvDropdownOption/VvDropdownOption.es.js +15 -7
  48. package/dist/components/VvInputText/VvInputText.es.js +279 -116
  49. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  50. package/dist/components/VvInputText/VvInputText.vue.d.ts +23 -41
  51. package/dist/components/VvInputText/index.d.ts +15 -33
  52. package/dist/components/VvNav/VvNav.es.js +18 -9
  53. package/dist/components/VvNav/VvNav.umd.js +1 -1
  54. package/dist/components/VvNav/index.d.ts +1 -1
  55. package/dist/components/VvProgress/VvProgress.es.js +15 -7
  56. package/dist/components/VvRadio/VvRadio.es.js +99 -21
  57. package/dist/components/VvRadio/VvRadio.umd.js +1 -1
  58. package/dist/components/VvRadio/VvRadio.vue.d.ts +4 -4
  59. package/dist/components/VvRadioGroup/VvRadioGroup.es.js +105 -22
  60. package/dist/components/VvRadioGroup/VvRadioGroup.umd.js +1 -1
  61. package/dist/components/VvRadioGroup/VvRadioGroup.vue.d.ts +4 -4
  62. package/dist/components/VvSelect/VvSelect.es.js +95 -21
  63. package/dist/components/VvSelect/VvSelect.umd.js +1 -1
  64. package/dist/components/VvSelect/VvSelect.vue.d.ts +5 -5
  65. package/dist/components/VvTab/VvTab.es.js +18 -9
  66. package/dist/components/VvTab/VvTab.umd.js +1 -1
  67. package/dist/components/VvTextarea/VvTextarea.es.js +103 -26
  68. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  69. package/dist/components/VvTextarea/VvTextarea.vue.d.ts +4 -4
  70. package/dist/components/VvTooltip/VvTooltip.es.js +15 -7
  71. package/dist/components/common/HintSlot.d.ts +4 -3
  72. package/dist/components/index.d.ts +5 -0
  73. package/dist/components/index.es.js +1212 -626
  74. package/dist/components/index.umd.js +1 -1
  75. package/dist/composables/alert/useAlert.d.ts +27 -0
  76. package/dist/composables/index.d.ts +1 -0
  77. package/dist/composables/index.es.js +81 -0
  78. package/dist/composables/index.umd.js +1 -0
  79. package/dist/constants.d.ts +14 -0
  80. package/dist/directives/index.es.js +15 -7
  81. package/dist/directives/v-tooltip.es.js +15 -7
  82. package/dist/icons.es.js +3 -3
  83. package/dist/icons.umd.js +1 -1
  84. package/dist/props/index.d.ts +107 -31
  85. package/dist/resolvers/unplugin.es.js +3 -0
  86. package/dist/resolvers/unplugin.umd.js +1 -1
  87. package/dist/stories/AccordionGroup/AccordionGroup.stories.d.ts +2 -2
  88. package/dist/stories/AccordionGroup/AccordionGroupSlots.stories.d.ts +54 -269
  89. package/dist/stories/Alert/Alert.settings.d.ts +3 -7
  90. package/dist/stories/AlertGroup/AlertGroupSlots.stories.d.ts +2 -2
  91. package/dist/stories/AlertGroup/AlertGroupWithComposable.stories.d.ts +6 -0
  92. package/dist/stories/Button/Button.settings.d.ts +3 -13
  93. package/dist/stories/Combobox/Combobox.settings.d.ts +117 -19
  94. package/dist/stories/InputText/InputText.settings.d.ts +31 -9
  95. package/dist/stories/InputText/InputText.stories.d.ts +0 -1
  96. package/dist/stories/InputText/InputTextMask.stories.d.ts +12 -0
  97. package/dist/stories/Nav/Nav.settings.d.ts +3 -21
  98. package/package.json +75 -66
  99. package/src/assets/icons/detailed.json +1 -1
  100. package/src/assets/icons/normal.json +1 -1
  101. package/src/assets/icons/simple.json +1 -1
  102. package/src/components/VvAction/VvAction.vue +2 -1
  103. package/src/components/VvAlert/VvAlert.vue +5 -1
  104. package/src/components/VvAlert/index.ts +3 -3
  105. package/src/components/VvAlertGroup/VvAlertGroup.vue +2 -0
  106. package/src/components/VvButton/VvButton.vue +1 -0
  107. package/src/components/VvCheckbox/VvCheckbox.vue +8 -1
  108. package/src/components/VvCheckboxGroup/VvCheckboxGroup.vue +8 -1
  109. package/src/components/VvCombobox/VvCombobox.vue +43 -23
  110. package/src/components/VvCombobox/index.ts +24 -0
  111. package/src/components/VvDialog/VvDialog.vue +22 -19
  112. package/src/components/VvDropdown/VvDropdown.vue +24 -18
  113. package/src/components/VvInputText/VvInputText.vue +177 -55
  114. package/src/components/VvInputText/index.ts +32 -34
  115. package/src/components/VvNav/VvNav.vue +1 -1
  116. package/src/components/VvNav/index.ts +1 -1
  117. package/src/components/VvRadio/VvRadio.vue +8 -1
  118. package/src/components/VvRadioGroup/VvRadioGroup.vue +8 -1
  119. package/src/components/VvSelect/VvSelect.vue +8 -1
  120. package/src/components/VvTextarea/VvTextarea.vue +16 -6
  121. package/src/components/common/HintSlot.ts +26 -13
  122. package/src/components/index.ts +5 -0
  123. package/src/composables/alert/useAlert.ts +103 -0
  124. package/src/composables/index.ts +1 -0
  125. package/src/constants.ts +26 -0
  126. package/src/props/index.ts +14 -11
  127. package/src/resolvers/unplugin.ts +3 -0
  128. package/src/stories/Alert/Alert.settings.ts +3 -1
  129. package/src/stories/AlertGroup/AlertGroup.test.ts +13 -0
  130. package/src/stories/AlertGroup/AlertGroupSlots.stories.ts +3 -3
  131. package/src/stories/AlertGroup/AlertGroupWithComposable.stories.ts +118 -0
  132. package/src/stories/Button/Button.settings.ts +5 -3
  133. package/src/stories/Combobox/Combobox.settings.ts +119 -2
  134. package/src/stories/Combobox/Combobox.test.ts +1 -1
  135. package/src/stories/InputText/InputText.settings.ts +36 -15
  136. package/src/stories/InputText/InputText.stories.ts +4 -12
  137. package/src/stories/InputText/InputText.test.ts +31 -15
  138. package/src/stories/InputText/InputTextMask.stories.ts +122 -0
  139. package/src/stories/Nav/Nav.settings.ts +3 -1
  140. package/src/stories/Tab/Tab.stories.ts +3 -3
  141. package/src/stories/Textarea/TextareaLength.stories.ts +1 -1
  142. package/src/types/alert.d.ts +20 -0
  143. /package/dist/components/{VvNavItemTitle → VvNav}/VvNavItemTitle.vue.d.ts +0 -0
  144. /package/dist/components/{VvNavSeparator → VvNav}/VvNavSeparator.d.ts +0 -0
  145. /package/src/components/{VvNavItemTitle → VvNav}/VvNavItemTitle.vue +0 -0
  146. /package/src/components/{VvNavSeparator → VvNav}/VvNavSeparator.ts +0 -0
@@ -66,7 +66,8 @@
66
66
  const hasProps = computed(() => {
67
67
  const toReturn = {
68
68
  ...dropdownAria?.value,
69
- 'aria-pressed': pressed.value ? true : undefined,
69
+ ariaPressed: pressed.value ? true : undefined,
70
+ ariaLabel: props.ariaLabel,
70
71
  role: role?.value,
71
72
  }
72
73
  switch (hasTag.value) {
@@ -34,7 +34,11 @@
34
34
  <slot name="header">
35
35
  <!-- @slot Before title slot -->
36
36
  <slot name="title::before" />
37
- <strong :id="hasTitleId" class="vv-alert__title">
37
+ <strong
38
+ v-if="$slots.title || title"
39
+ :id="hasTitleId"
40
+ class="vv-alert__title"
41
+ >
38
42
  <!-- @slot Title slot -->
39
43
  <slot name="title">
40
44
  {{ title }}
@@ -40,7 +40,7 @@ export const VvAlertProps = {
40
40
  */
41
41
  title: {
42
42
  type: String,
43
- default: '',
43
+ default: undefined,
44
44
  },
45
45
  /**
46
46
  * The alert content
@@ -49,7 +49,7 @@ export const VvAlertProps = {
49
49
  */
50
50
  content: {
51
51
  type: String,
52
- default: '',
52
+ default: undefined,
53
53
  },
54
54
  /**
55
55
  * The alert footer
@@ -58,7 +58,7 @@ export const VvAlertProps = {
58
58
  */
59
59
  footer: {
60
60
  type: String,
61
- default: '',
61
+ default: undefined,
62
62
  },
63
63
  /**
64
64
  * The alert role
@@ -8,8 +8,10 @@
8
8
  import { useVvAlertGroup, VvAlertGroupEvents, VvAlertGroupProps } from '.'
9
9
  import VvAlert from '../VvAlert/VvAlert.vue'
10
10
 
11
+ // props and emit
11
12
  const props = defineProps(VvAlertGroupProps)
12
13
  const emit = defineEmits(VvAlertGroupEvents)
14
+
13
15
  const { hasProps, hasTransition } = useVvAlertGroup(props, emit)
14
16
 
15
17
  const alertGroupTransitionHandlers = {
@@ -118,6 +118,7 @@
118
118
  href,
119
119
  target,
120
120
  rel,
121
+ ariaLabel,
121
122
  }"
122
123
  :id="hasId"
123
124
  ref="element"
@@ -13,6 +13,13 @@
13
13
  const emit = defineEmits(VvCheckboxEvents)
14
14
  const slots = useSlots()
15
15
 
16
+ // props merged with volver defaults (now only for labels)
17
+ const propsDefaults = useDefaults<typeof VvCheckboxProps>(
18
+ 'VvCheckbox',
19
+ VvCheckboxProps,
20
+ props,
21
+ )
22
+
16
23
  // data
17
24
  const {
18
25
  id,
@@ -150,7 +157,7 @@
150
157
  hasHintLabelOrSlot,
151
158
  hasInvalidLabelOrSlot,
152
159
  hintSlotScope,
153
- } = HintSlotFactory(props, slots)
160
+ } = HintSlotFactory(propsDefaults, slots)
154
161
  </script>
155
162
 
156
163
  <template>
@@ -17,6 +17,13 @@
17
17
  const emit = defineEmits(VvCheckboxGroupEvents)
18
18
  const slots = useSlots()
19
19
 
20
+ // props merged with volver defaults (now only for labels)
21
+ const propsDefaults = useDefaults<typeof VvCheckboxGroupProps>(
22
+ 'VvCheckboxGroup',
23
+ VvCheckboxGroupProps,
24
+ props,
25
+ )
26
+
20
27
  // data
21
28
  const modelValue = useVModel(props, 'modelValue', emit)
22
29
  const { disabled, readonly, vertical, valid, invalid, modifiers } =
@@ -56,7 +63,7 @@
56
63
  value: getOptionValue(option),
57
64
  }
58
65
  }
59
- const { HintSlot, hintSlotScope } = HintSlotFactory(props, slots)
66
+ const { HintSlot, hintSlotScope } = HintSlotFactory(propsDefaults, slots)
60
67
  </script>
61
68
 
62
69
  <template>
@@ -12,6 +12,7 @@
12
12
 
13
13
  <script setup lang="ts">
14
14
  import type { Ref } from 'vue'
15
+ import { toRefs } from 'vue'
15
16
  import { VvComboboxProps, VvComboboxEvents } from '.'
16
17
  import VvIcon from '../VvIcon/VvIcon.vue'
17
18
  import VvDropdown from '../VvDropdown/VvDropdown.vue'
@@ -50,7 +51,7 @@
50
51
  hasHintLabelOrSlot,
51
52
  hasInvalidLabelOrSlot,
52
53
  hintSlotScope,
53
- } = HintSlotFactory(props, slots)
54
+ } = HintSlotFactory(propsDefaults, slots)
54
55
 
55
56
  // template ref
56
57
  const inputEl: Ref<HTMLElement | null> = ref(null)
@@ -84,7 +85,7 @@
84
85
  const searchText = ref('')
85
86
  const debouncedSearchText = refDebounced(
86
87
  searchText,
87
- Number(props.debounceSearch),
88
+ computed(() => Number(props.debounceSearch)),
88
89
  )
89
90
  watch(debouncedSearchText, () =>
90
91
  emit('change:search', debouncedSearchText.value),
@@ -105,7 +106,7 @@
105
106
  expanded.value = false
106
107
  }
107
108
  const onAfterExpand = () => {
108
- if (searchable.value) {
109
+ if (propsDefaults.value.searchable) {
109
110
  if (inputSearchEl.value) {
110
111
  inputSearchEl.value.focus({
111
112
  preventScroll: true,
@@ -114,7 +115,7 @@
114
115
  }
115
116
  }
116
117
  const onAfterCollapse = () => {
117
- if (searchable.value) {
118
+ if (propsDefaults.value.searchable) {
118
119
  searchText.value = ''
119
120
  }
120
121
  }
@@ -131,7 +132,6 @@
131
132
  valid,
132
133
  invalid,
133
134
  floating,
134
- searchable,
135
135
  } = toRefs(props)
136
136
  const hasId = useUniqueId(id)
137
137
  const hasHintId = computed(() => `${hasId.value}-hint`)
@@ -139,6 +139,10 @@
139
139
  const hasSearchId = computed(() => `${hasId.value}-search`)
140
140
  const hasLabelId = computed(() => `${hasId.value}-label`)
141
141
 
142
+ // loading
143
+ const localLoading = ref(false)
144
+ const isLoading = computed(() => localLoading.value || loading.value)
145
+
142
146
  // ref
143
147
  const dropdownEl = ref()
144
148
 
@@ -162,7 +166,7 @@
162
166
  modifiers,
163
167
  computed(() => ({
164
168
  disabled: disabled.value,
165
- loading: loading.value,
169
+ loading: isLoading.value,
166
170
  readonly: readonly.value,
167
171
  'icon-before': Boolean(hasIconBefore.value),
168
172
  'icon-after': Boolean(hasIconAfter.value),
@@ -183,7 +187,18 @@
183
187
  } = useOptions(props)
184
188
 
185
189
  // options filtered by search text
186
- const filteredOptions = computed(() => {
190
+ const filteredOptions = computedAsync(async () => {
191
+ if (propsDefaults.value.searchFunction) {
192
+ localLoading.value = true
193
+ const toReturn = await Promise.resolve(
194
+ propsDefaults.value.searchFunction(
195
+ debouncedSearchText.value,
196
+ props.options,
197
+ ),
198
+ )
199
+ localLoading.value = false
200
+ return toReturn
201
+ }
187
202
  return props.options?.filter((option) => {
188
203
  return getOptionLabel(option)
189
204
  .toLowerCase()
@@ -221,12 +236,15 @@
221
236
  } else if (props.modelValue) {
222
237
  selectedValues = [props.modelValue]
223
238
  }
224
- const options = props.options.reduce((acc, value) => {
225
- if (isGroup(value)) {
226
- return [...acc, ...getOptionGrouped(value)]
227
- }
228
- return [...acc, value]
229
- }, [] as Array<Option | string>)
239
+ const options = props.options.reduce(
240
+ (acc, value) => {
241
+ if (isGroup(value)) {
242
+ return [...acc, ...getOptionGrouped(value)]
243
+ }
244
+ return [...acc, value]
245
+ },
246
+ [] as Array<Option | string>,
247
+ )
230
248
 
231
249
  return options.filter((option) => {
232
250
  if (isGroup(option)) {
@@ -304,7 +322,7 @@
304
322
  invalid: invalid.value,
305
323
  invalidLabel: propsDefaults.value.invalidLabel,
306
324
  hintLabel: propsDefaults.value.hintLabel,
307
- loading: loading.value,
325
+ loading: isLoading.value,
308
326
  loadingLabel: propsDefaults.value.loadingLabel,
309
327
  disabled: disabled.value,
310
328
  readonly: readonly.value,
@@ -333,8 +351,8 @@
333
351
  flip: propsDefaults.value.flip,
334
352
  autoPlacement: propsDefaults.value.autoPlacement,
335
353
  arrow: propsDefaults.value.arrow,
336
- autofocusFirst: searchable.value
337
- ? false
354
+ autofocusFirst: propsDefaults.value.searchable
355
+ ? true
338
356
  : propsDefaults.value.autofocusFirst,
339
357
  triggerWidth: propsDefaults.value.triggerWidth,
340
358
  modifiers: propsDefaults.value.dropdownModifiers,
@@ -369,7 +387,7 @@
369
387
  <label
370
388
  v-if="label"
371
389
  :id="hasLabelId"
372
- :for="searchable ? hasSearchId : undefined"
390
+ :for="propsDefaults.searchable ? hasSearchId : undefined"
373
391
  >
374
392
  {{ label }}
375
393
  </label>
@@ -383,14 +401,15 @@
383
401
  @after-collapse="onAfterCollapse"
384
402
  >
385
403
  <template
386
- v-if="searchable || $slots['dropdown::before']"
404
+ v-if="
405
+ propsDefaults.searchable || $slots['dropdown::before']
406
+ "
387
407
  #before
388
408
  >
389
409
  <!-- @slot Slot before dropdown items -->
390
410
  <slot name="dropdown::before" />
391
411
  <input
392
- v-if="searchable"
393
- v-show="expanded"
412
+ v-if="propsDefaults.searchable && !disabled"
394
413
  :id="hasSearchId"
395
414
  ref="inputSearchEl"
396
415
  v-model="searchText"
@@ -461,6 +480,7 @@
461
480
  :aria-label="
462
481
  propsDefaults.deselectActionLabel
463
482
  "
483
+ type="button"
464
484
  @click.stop="onInput(option)"
465
485
  >
466
486
  <VvIcon name="close" />
@@ -484,7 +504,7 @@
484
504
  </div>
485
505
  </template>
486
506
  <template #items>
487
- <template v-if="filteredOptions.length">
507
+ <template v-if="!disabled && filteredOptions?.length">
488
508
  <template
489
509
  v-for="(option, index) in filteredOptions"
490
510
  :key="index"
@@ -566,7 +586,7 @@
566
586
  {{ propsDefaults.noOptionsLabel }}
567
587
  </slot>
568
588
  </VvDropdownOption>
569
- <VvDropdownOption v-else modifiers="inert">
589
+ <VvDropdownOption v-else-if="!disabled" modifiers="inert">
570
590
  <!-- @slot Slot for no results available -->
571
591
  <slot name="no-results">
572
592
  {{ propsDefaults.noResultsLabel }}
@@ -579,7 +599,7 @@
579
599
  <!-- Close button if dropdown custom position is enabled and floating-ui disabled -->
580
600
  <VvButton
581
601
  v-if="dropdownEl?.customPosition"
582
- label="Close"
602
+ :label="propsDefaults.closeLabel"
583
603
  modifiers="secondary"
584
604
  @click="dropdownEl.hide()"
585
605
  />
@@ -16,6 +16,7 @@ import {
16
16
  DropdownProps,
17
17
  LabelProps,
18
18
  } from '../../props'
19
+ import type { Option } from '../../types/generic'
19
20
 
20
21
  export const VvComboboxEvents = [
21
22
  'update:modelValue',
@@ -40,6 +41,13 @@ export const VvComboboxProps = {
40
41
  ...UnselectableProps,
41
42
  ...DropdownProps,
42
43
  ...LabelProps,
44
+ /**
45
+ * Dropdown show / hide transition name
46
+ */
47
+ transitionName: {
48
+ type: String,
49
+ default: 'vv-dropdown--mobile-fade-block',
50
+ },
43
51
  /**
44
52
  * modelValue can be a string, number, boolean, object or array of string, number, boolean, object
45
53
  */
@@ -71,6 +79,10 @@ export const VvComboboxProps = {
71
79
  * Label for deselected option hint
72
80
  */
73
81
  deselectHintLabel: { type: String, default: 'Press enter to remove' },
82
+ /**
83
+ * Label close button
84
+ */
85
+ closeLabel: { type: String, default: 'Close' },
74
86
  /**
75
87
  * Select input placeholder
76
88
  */
@@ -79,6 +91,18 @@ export const VvComboboxProps = {
79
91
  * Use input text to search on options
80
92
  */
81
93
  searchable: Boolean,
94
+ /**
95
+ * Search function to filter options
96
+ */
97
+ searchFunction: {
98
+ type: Function as PropType<
99
+ (
100
+ search: string,
101
+ options: (Option | string)[],
102
+ ) => (Option | string)[] | Promise<(Option | string)[]>
103
+ >,
104
+ default: undefined,
105
+ },
82
106
  /**
83
107
  * On searchable select is the input search placeholder
84
108
  */
@@ -15,16 +15,16 @@
15
15
  const dialogEl: Ref<HTMLDialogElement | undefined> = ref()
16
16
 
17
17
  // data
18
+ const modelValue = useVModel(props, 'modelValue', emit)
18
19
  const localModelValue = ref(false)
19
- const modelValue = computed({
20
- get() {
21
- return props.modelValue ?? localModelValue.value
22
- },
23
- set(value) {
24
- if (props.modelValue === undefined) {
25
- localModelValue.value = value
20
+ const isOpened = computed({
21
+ get: () => modelValue.value ?? localModelValue.value,
22
+ set: (newValue) => {
23
+ if (modelValue.value === undefined) {
24
+ localModelValue.value = newValue
25
+ return
26
26
  }
27
- emit('update:modelValue', value)
27
+ modelValue.value = newValue
28
28
  },
29
29
  })
30
30
 
@@ -49,12 +49,16 @@
49
49
  const transitioName = computed(() => `vv-dialog--${props.transition}`)
50
50
  const dialogTransitionHandlers = {
51
51
  'before-enter': () => {
52
- dialogEl.value?.showModal()
52
+ if (!dialogEl.value?.open) {
53
+ dialogEl.value?.showModal()
54
+ }
53
55
  emit('open')
54
56
  emit('before-enter')
55
57
  },
56
58
  'after-leave': () => {
57
- dialogEl.value?.close()
59
+ if (dialogEl.value?.open) {
60
+ dialogEl.value?.close()
61
+ }
58
62
  emit('close')
59
63
  emit('after-leave')
60
64
  },
@@ -81,36 +85,35 @@
81
85
  // methods
82
86
  onClickOutside(modalWrapper, () => {
83
87
  if (!props.keepOpen) {
84
- modelValue.value = false
88
+ close()
85
89
  }
86
90
  })
87
91
 
88
92
  function close() {
89
- modelValue.value = false
93
+ isOpened.value = false
90
94
  }
91
95
 
92
96
  function open() {
93
- modelValue.value = true
97
+ isOpened.value = true
94
98
  }
95
99
 
96
100
  defineExpose({ close, open })
97
101
 
98
- // keyboard
99
- onKeyStroke('Escape', (e) => {
100
- if (modelValue.value) {
101
- e.preventDefault()
102
+ const onCancel = () => {
103
+ if (!props.keepOpen) {
102
104
  close()
103
105
  }
104
- })
106
+ }
105
107
  </script>
106
108
 
107
109
  <template>
108
110
  <Transition :name="transitioName" v-on="dialogTransitionHandlers">
109
111
  <dialog
110
- v-show="modelValue"
112
+ v-show="isOpened"
111
113
  v-bind="dialogAttrs"
112
114
  ref="dialogEl"
113
115
  :class="dialogClass"
116
+ @cancel.stop.prevent="onCancel"
114
117
  >
115
118
  <article ref="modalWrapper" class="vv-dialog__wrapper">
116
119
  <header v-if="$slots.header || title" class="vv-dialog__header">
@@ -25,6 +25,7 @@
25
25
  ShiftOptions,
26
26
  SizeOptions,
27
27
  } from '../../types/floating-ui'
28
+ import { Side, Strategy } from '../../constants'
28
29
 
29
30
  // props, emit and attrs
30
31
  const props = defineProps(VvDropdownProps)
@@ -96,7 +97,7 @@
96
97
  }
97
98
  } else if (props.flip) {
98
99
  if (typeof props.flip === 'boolean') {
99
- toReturn.push(flip())
100
+ toReturn.push(flip({ fallbackStrategy: 'initialPlacement' }))
100
101
  } else {
101
102
  toReturn.push(flip(props.flip as FlipOptions))
102
103
  }
@@ -157,11 +158,15 @@
157
158
 
158
159
  return toReturn
159
160
  })
160
- const { x, y, strategy, middlewareData, placement } = useFloating(
161
+ const { x, y, middlewareData, placement, strategy } = useFloating(
161
162
  referenceEl,
162
163
  floatingEl,
163
164
  {
164
- whileElementsMounted: autoUpdate,
165
+ whileElementsMounted: (...args) => {
166
+ return autoUpdate(...args, {
167
+ animationFrame: props.strategy === Strategy.fixed,
168
+ })
169
+ },
165
170
  placement: computed(() => props.placement),
166
171
  strategy: computed(() => props.strategy),
167
172
  middleware,
@@ -171,16 +176,17 @@
171
176
  if (hasCustomPosition.value) {
172
177
  return undefined
173
178
  }
179
+ const width =
180
+ props.triggerWidth && referenceEl.value
181
+ ? `${referenceEl.value?.offsetWidth}px`
182
+ : undefined
174
183
  return {
175
184
  position: strategy.value,
176
185
  top: `${y.value ?? 0}px`,
177
186
  left: `${x.value ?? 0}px`,
178
- maxWidth: maxWidth.value,
187
+ maxWidth: width ? undefined : maxWidth.value,
179
188
  maxHeight: maxHeight.value,
180
- width:
181
- props.triggerWidth && referenceEl.value
182
- ? `${referenceEl.value.offsetWidth}px`
183
- : undefined,
189
+ width,
184
190
  }
185
191
  })
186
192
 
@@ -188,20 +194,20 @@
188
194
  const side = computed(
189
195
  () =>
190
196
  placement.value.split('-')[0] as
191
- | 'top'
192
- | 'right'
193
- | 'bottom'
194
- | 'left',
197
+ | Side.top
198
+ | Side.right
199
+ | Side.bottom
200
+ | Side.left,
195
201
  )
196
202
  const arrowPlacement = computed(() => {
197
203
  if (hasCustomPosition.value) {
198
204
  return undefined
199
205
  }
200
206
  const staticSide = {
201
- top: 'bottom',
202
- right: 'left',
203
- bottom: 'top',
204
- left: 'right',
207
+ [Side.top]: Side.bottom,
208
+ [Side.right]: Side.left,
209
+ [Side.bottom]: Side.top,
210
+ [Side.left]: Side.right,
205
211
  }[side.value]
206
212
  return {
207
213
  left:
@@ -266,7 +272,7 @@
266
272
  onClickOutside(
267
273
  floatingEl,
268
274
  () => {
269
- if (!props.keepOpen) {
275
+ if (!props.keepOpen && expanded.value) {
270
276
  expanded.value = false
271
277
  }
272
278
  },
@@ -314,7 +320,7 @@
314
320
  }
315
321
  return [
316
322
  ...element.querySelectorAll(
317
- 'a[href], button, input, textarea, select, details,[tabindex]:not([tabindex="-1"])',
323
+ 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])',
318
324
  ),
319
325
  ].filter(
320
326
  (el) =>