Skip to content

Commit 9cbe778

Browse files
committed
fix(VSelect): don't close menu if submenus are open
fixes #16645 Using Ψ as a private prefix due to vuejs/core#7710
1 parent f00e001 commit 9cbe778

File tree

5 files changed

+36
-9
lines changed

5 files changed

+36
-9
lines changed

packages/api-generator/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function inspect (project: Project, node?: Node<ts.Node>) {
1515
if (definition.properties) {
1616
// Exclude private properties
1717
definition.properties = Object.fromEntries(Object.entries(definition.properties)
18-
.filter(([name]) => !name.startsWith('_')))
18+
.filter(([name]) => !name.startsWith('_') && !name.startsWith('Ψ')))
1919
}
2020
return definition
2121
}

packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,15 @@ export const VAutocomplete = genericComponent<new <
107107
const vTextFieldRef = ref()
108108
const isFocused = ref(false)
109109
const isPristine = ref(true)
110-
const menu = useProxiedModel(props, 'menu')
110+
const vMenuRef = ref<VMenu>()
111+
const _menu = useProxiedModel(props, 'menu')
112+
const menu = computed({
113+
get: () => _menu.value,
114+
set: v => {
115+
if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return
116+
_menu.value = v
117+
},
118+
})
111119
const { items, transformIn, transformOut } = useItems(props)
112120
const search = useProxiedModel(props, 'search', '')
113121
const model = useProxiedModel(
@@ -284,6 +292,7 @@ export const VAutocomplete = genericComponent<new <
284292
default: () => (
285293
<>
286294
<VMenu
295+
ref={ vMenuRef }
287296
v-model={ menu.value }
288297
activator="parent"
289298
contentClass="v-autocomplete__content"

packages/vuetify/src/components/VCombobox/VCombobox.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,15 @@ export const VCombobox = genericComponent<new <
109109
const vTextFieldRef = ref()
110110
const isFocused = ref(false)
111111
const isPristine = ref(true)
112-
const menu = useProxiedModel(props, 'menu')
112+
const vMenuRef = ref<VMenu>()
113+
const _menu = useProxiedModel(props, 'menu')
114+
const menu = computed({
115+
get: () => _menu.value,
116+
set: v => {
117+
if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return
118+
_menu.value = v
119+
},
120+
})
113121
const selectionIndex = ref(-1)
114122
const color = computed(() => vTextFieldRef.value?.color)
115123
const { items, transformIn, transformOut } = useItems(props)
@@ -364,6 +372,7 @@ export const VCombobox = genericComponent<new <
364372
default: () => (
365373
<>
366374
<VMenu
375+
ref={ vMenuRef }
367376
v-model={ menu.value }
368377
activator="parent"
369378
contentClass="v-combobox__content"

packages/vuetify/src/components/VMenu/VMenu.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,17 @@ export const VMenu = genericComponent<OverlaySlots>()({
5353
const overlay = ref<VOverlay>()
5454

5555
const parent = inject(VMenuSymbol, null)
56-
let openChildren = 0
56+
const openChildren = ref(0)
5757
provide(VMenuSymbol, {
5858
register () {
59-
++openChildren
59+
++openChildren.value
6060
},
6161
unregister () {
62-
--openChildren
62+
--openChildren.value
6363
},
6464
closeParents () {
6565
setTimeout(() => {
66-
if (!openChildren) {
66+
if (!openChildren.value) {
6767
isActive.value = false
6868
parent?.closeParents()
6969
}
@@ -115,7 +115,7 @@ export const VMenu = genericComponent<OverlaySlots>()({
115115
)
116116
})
117117

118-
return forwardRefs({ id }, overlay)
118+
return forwardRefs({ id, ΨopenChildren: openChildren }, overlay)
119119
},
120120
})
121121

packages/vuetify/src/components/VSelect/VSelect.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,15 @@ export const VSelect = genericComponent<new <
111111
setup (props, { slots }) {
112112
const { t } = useLocale()
113113
const vTextFieldRef = ref()
114-
const menu = useProxiedModel(props, 'menu')
114+
const vMenuRef = ref<VMenu>()
115+
const _menu = useProxiedModel(props, 'menu')
116+
const menu = computed({
117+
get: () => _menu.value,
118+
set: v => {
119+
if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return
120+
_menu.value = v
121+
},
122+
})
115123
const { items, transformIn, transformOut } = useItems(props)
116124
const model = useProxiedModel(
117125
props,
@@ -239,6 +247,7 @@ export const VSelect = genericComponent<new <
239247
default: () => (
240248
<>
241249
<VMenu
250+
ref={ vMenuRef }
242251
v-model={ menu.value }
243252
activator="parent"
244253
contentClass="v-select__content"

0 commit comments

Comments
 (0)