From 14be656999d8061c6623cb11ef611fe06e23296e Mon Sep 17 00:00:00 2001 From: Yuchao Date: Sun, 19 Jan 2025 22:34:12 +1100 Subject: [PATCH] fix(VTreeview): Incorrect isOpen state in the prepend slot when using return-object (#20884) --- .../vuetify/src/composables/nested/nested.ts | 2 +- .../src/labs/VTreeview/VTreeviewChildren.tsx | 2 +- .../src/labs/VTreeview/VTreeviewItem.tsx | 4 +-- .../__tests__/VTreeview.spec.browser.tsx | 33 +++++++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/vuetify/src/composables/nested/nested.ts b/packages/vuetify/src/composables/nested/nested.ts index a97188b1c0f..b3ede9a3b84 100644 --- a/packages/vuetify/src/composables/nested/nested.ts +++ b/packages/vuetify/src/composables/nested/nested.ts @@ -339,7 +339,7 @@ export const useNestedItem = (id: Ref, isGroup: boolean) => { isActivated: computed(() => parent.root.activated.value.has(toRaw(computedId.value))), select: (selected: boolean, e?: Event) => parent.root.select(computedId.value, selected, e), isSelected: computed(() => parent.root.selected.value.get(toRaw(computedId.value)) === 'on'), - isIndeterminate: computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'), + isIndeterminate: computed(() => parent.root.selected.value.get(toRaw(computedId.value)) === 'indeterminate'), isLeaf: computed(() => !parent.root.children.value.get(computedId.value)), isGroupActivator: parent.isGroupActivator, } diff --git a/packages/vuetify/src/labs/VTreeview/VTreeviewChildren.tsx b/packages/vuetify/src/labs/VTreeview/VTreeviewChildren.tsx index 89a88fdfc7c..d4a6694f837 100644 --- a/packages/vuetify/src/labs/VTreeview/VTreeviewChildren.tsx +++ b/packages/vuetify/src/labs/VTreeview/VTreeviewChildren.tsx @@ -143,7 +143,7 @@ export const VTreeviewChildren = genericComponent diff --git a/packages/vuetify/src/labs/VTreeview/VTreeviewItem.tsx b/packages/vuetify/src/labs/VTreeview/VTreeviewItem.tsx index b6968afa059..95732952a7f 100644 --- a/packages/vuetify/src/labs/VTreeview/VTreeviewItem.tsx +++ b/packages/vuetify/src/labs/VTreeview/VTreeviewItem.tsx @@ -12,7 +12,7 @@ import { IconValue } from '@/composables/icons' import { useLink } from '@/composables/router' // Utilities -import { computed, inject, ref } from 'vue' +import { computed, inject, ref, toRaw } from 'vue' import { EventProp, genericComponent, omit, propsFactory, useRender } from '@/util' // Types @@ -68,7 +68,7 @@ export const VTreeviewItem = genericComponent()({ 'v-treeview-item', { 'v-treeview-item--activatable-group-activator': isActivatableGroupActivator.value, - 'v-treeview-item--filtered': visibleIds.value && !visibleIds.value.has(vListItemRef.value?.id), + 'v-treeview-item--filtered': visibleIds.value && !visibleIds.value.has(toRaw(vListItemRef.value?.id)), }, props.class, ]} diff --git a/packages/vuetify/src/labs/VTreeview/__tests__/VTreeview.spec.browser.tsx b/packages/vuetify/src/labs/VTreeview/__tests__/VTreeview.spec.browser.tsx index ec74dfca194..d2bee933f52 100644 --- a/packages/vuetify/src/labs/VTreeview/__tests__/VTreeview.spec.browser.tsx +++ b/packages/vuetify/src/labs/VTreeview/__tests__/VTreeview.spec.browser.tsx @@ -672,4 +672,37 @@ describe.each([ expect(el).toBeVisible() }) }) + + // https://github.com/vuetifyjs/vuetify/issues/20830 + it('should return correct isOpen state in prepend slot', async () => { + render(() => ( + + {{ + prepend: ({ isOpen }) => ({ `${isOpen}` }), + }} + + )) + + await userEvent.click(screen.getByText(/Vuetify Human Resources/)) + const itemsPrepend = screen.getAllByCSS('.v-treeview-item .v-list-item__prepend .prepend-is-open') + expect(itemsPrepend[0]).toHaveTextContent(/^true$/) + expect(itemsPrepend[1]).toHaveTextContent(/^false$/) + + await userEvent.click(screen.getByText(/Core team/)) + expect(itemsPrepend[0]).toHaveTextContent(/^true$/) + expect(itemsPrepend[1]).toHaveTextContent(/^true$/) + + await userEvent.click(screen.getByText(/Core team/)) + expect(itemsPrepend[0]).toHaveTextContent(/^true$/) + expect(itemsPrepend[1]).toHaveTextContent(/^false$/) + + await userEvent.click(screen.getByText(/Vuetify Human Resources/)) + expect(itemsPrepend[0]).toHaveTextContent(/^false$/) + expect(itemsPrepend[1]).toHaveTextContent(/^false$/) + }) })